summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiika Pekkarinen <miipekk@ihme.org>2008-03-16 13:55:16 +0000
committerMiika Pekkarinen <miipekk@ihme.org>2008-03-16 13:55:16 +0000
commit19c6e66c1353993659ee007a6c1792a6b0b7ba13 (patch)
tree1dd7f88282b2e543fb5b22458fcb2f3bf1c7eb80
parent478ba0afa11061a620e44cd9cc60debd955b1b33 (diff)
downloadrockbox-19c6e66c1353993659ee007a6c1792a6b0b7ba13.tar.gz
rockbox-19c6e66c1353993659ee007a6c1792a6b0b7ba13.zip
Implement the playback event handling as a system-wide multi-purpose event system. Unified mpeg.c and playback.c audio event handling. Converted ata_idle_notify to use the new event handling system also.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16682 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/lang/english.lang16
-rw-r--r--apps/main.c2
-rw-r--r--apps/playback.c58
-rw-r--r--apps/playback.h14
-rw-r--r--apps/scrobbler.c17
-rw-r--r--apps/settings.c20
-rw-r--r--apps/tagtree.c11
-rw-r--r--firmware/SOURCES1
-rw-r--r--firmware/ata_idle_notify.c61
-rw-r--r--firmware/events.c88
-rw-r--r--firmware/export/ata_idle_notify.h10
-rw-r--r--firmware/export/events.h51
-rw-r--r--firmware/export/mpeg.h1
-rw-r--r--firmware/mpeg.c41
14 files changed, 182 insertions, 209 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 3911223d2d..e5df04a460 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -8191,29 +8191,27 @@
8191</phrase> 8191</phrase>
8192<phrase> 8192<phrase>
8193 id: LANG_SETTINGS_SAVE_FAILED 8193 id: LANG_SETTINGS_SAVE_FAILED
8194 desc: displayed if save settings has failed 8194 desc: DEPRECATED
8195 user: 8195 user:
8196 <source> 8196 <source>
8197 *: "Save Failed" 8197 *: ""
8198 </source> 8198 </source>
8199 <dest> 8199 <dest>
8200 *: "Save Failed" 8200 *: ""
8201 </dest> 8201 </dest>
8202 <voice> 8202 <voice>
8203 *: "Save Failed" 8203 *: ""
8204 </voice> 8204 </voice>
8205</phrase> 8205</phrase>
8206<phrase> 8206<phrase>
8207 id: LANG_SETTINGS_PARTITION 8207 id: LANG_SETTINGS_PARTITION
8208 desc: if save settings has failed 8208 desc: DEPRECATED
8209 user: 8209 user:
8210 <source> 8210 <source>
8211 *: "No partition?" 8211 *: ""
8212 player: "Partition?"
8213 </source> 8212 </source>
8214 <dest> 8213 <dest>
8215 *: "No partition?" 8214 *: ""
8216 player: "Partition?"
8217 </dest> 8215 </dest>
8218 <voice> 8216 <voice>
8219 *: "" 8217 *: ""
diff --git a/apps/main.c b/apps/main.c
index 598597520f..5dd92e5e02 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -19,7 +19,6 @@
19#include "config.h" 19#include "config.h"
20 20
21#include "ata.h" 21#include "ata.h"
22#include "ata_idle_notify.h"
23#include "disk.h" 22#include "disk.h"
24#include "fat.h" 23#include "fat.h"
25#include "lcd.h" 24#include "lcd.h"
@@ -428,7 +427,6 @@ static void init(void)
428 } 427 }
429#endif 428#endif
430 429
431 ata_idle_notify_init();
432 rc = ata_init(); 430 rc = ata_init();
433 if(rc) 431 if(rc)
434 { 432 {
diff --git a/apps/playback.c b/apps/playback.c
index b36f68f135..ee1787e612 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -245,13 +245,6 @@ static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer
245 */ 245 */
246static bool codec_requested_stop = false; 246static bool codec_requested_stop = false;
247 247
248struct playback_event {
249 enum PLAYBACK_EVENT_TYPE type;
250 void (*callback)(void *data);
251};
252
253struct playback_event events[PLAYBACK_MAX_EVENTS];
254
255static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */ 248static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
256 249
257/* Multiple threads */ 250/* Multiple threads */
@@ -1447,51 +1440,6 @@ static void codec_thread(void)
1447 1440
1448/* --- Audio thread --- */ 1441/* --- Audio thread --- */
1449 1442
1450void playback_add_event(enum PLAYBACK_EVENT_TYPE type, void (*handler))
1451{
1452 int i;
1453
1454 /* Try to find a free slot. */
1455 for (i = 0; i < PLAYBACK_MAX_EVENTS; i++)
1456 {
1457 if (events[i].callback == NULL)
1458 {
1459 events[i].type = type;
1460 events[i].callback = handler;
1461 return;
1462 }
1463 }
1464
1465 panicf("playback event line full");
1466}
1467
1468void playback_remove_event(enum PLAYBACK_EVENT_TYPE type, void (*handler))
1469{
1470 int i;
1471
1472 for (i = 0; i < PLAYBACK_MAX_EVENTS; i++)
1473 {
1474 if (events[i].type == type && events[i].callback == handler)
1475 {
1476 events[i].callback = NULL;
1477 return;
1478 }
1479 }
1480
1481 panicf("playback event not found");
1482}
1483
1484static void send_event(enum PLAYBACK_EVENT_TYPE type, void *data)
1485{
1486 int i;
1487
1488 for (i = 0; i < PLAYBACK_MAX_EVENTS; i++)
1489 {
1490 if (events[i].type == type && events[i].callback != NULL)
1491 events[i].callback(data);
1492 }
1493}
1494
1495static bool audio_have_tracks(void) 1443static bool audio_have_tracks(void)
1496{ 1444{
1497 return (audio_track_count() != 0); 1445 return (audio_track_count() != 0);
@@ -1783,7 +1731,7 @@ static bool audio_load_track(int offset, bool start_play)
1783 { 1731 {
1784 if (get_metadata(&id3, fd, trackname)) 1732 if (get_metadata(&id3, fd, trackname))
1785 { 1733 {
1786 send_event(PLAYBACK_EVENT_TRACK_BUFFER, &id3); 1734 send_event(PLAYBACK_EVENT_TRACK_BUFFER, false, &id3);
1787 1735
1788 tracks[track_widx].id3_hid = 1736 tracks[track_widx].id3_hid =
1789 bufalloc(&id3, sizeof(struct mp3entry), TYPE_ID3); 1737 bufalloc(&id3, sizeof(struct mp3entry), TYPE_ID3);
@@ -2020,7 +1968,7 @@ static int audio_check_new_track(void)
2020 bool end_of_playlist; /* Temporary flag, not the same as playlist_end */ 1968 bool end_of_playlist; /* Temporary flag, not the same as playlist_end */
2021 1969
2022 /* Now it's good time to send track unbuffer events. */ 1970 /* Now it's good time to send track unbuffer events. */
2023 send_event(PLAYBACK_EVENT_TRACK_FINISH, &curtrack_id3); 1971 send_event(PLAYBACK_EVENT_TRACK_FINISH, false, &curtrack_id3);
2024 1972
2025 if (dir_skip) 1973 if (dir_skip)
2026 { 1974 {
@@ -2391,7 +2339,7 @@ static void audio_finalise_track_change(void)
2391 bufgetid3(prev_ti->id3_hid)->elapsed = 0; 2339 bufgetid3(prev_ti->id3_hid)->elapsed = 0;
2392 } 2340 }
2393 2341
2394 send_event(PLAYBACK_EVENT_TRACK_CHANGE, &curtrack_id3); 2342 send_event(PLAYBACK_EVENT_TRACK_CHANGE, false, &curtrack_id3);
2395 2343
2396 track_changed = true; 2344 track_changed = true;
2397 playlist_update_resume_info(audio_current_track()); 2345 playlist_update_resume_info(audio_current_track());
diff --git a/apps/playback.h b/apps/playback.h
index 14ba35cea4..0b78eb3bcb 100644
--- a/apps/playback.h
+++ b/apps/playback.h
@@ -24,6 +24,7 @@
24 24
25#include "id3.h" 25#include "id3.h"
26#include "mp3data.h" 26#include "mp3data.h"
27#include "events.h"
27 28
28#define CODEC_IDX_AUDIO 0 29#define CODEC_IDX_AUDIO 0
29#define CODEC_IDX_VOICE 1 30#define CODEC_IDX_VOICE 1
@@ -39,13 +40,6 @@
39 40
40#define MAX_TRACK_MASK (MAX_TRACK-1) 41#define MAX_TRACK_MASK (MAX_TRACK-1)
41 42
42#define PLAYBACK_MAX_EVENTS 4
43enum PLAYBACK_EVENT_TYPE {
44 PLAYBACK_EVENT_TRACK_BUFFER,
45 PLAYBACK_EVENT_TRACK_FINISH,
46 PLAYBACK_EVENT_TRACK_CHANGE,
47};
48
49/* Functions */ 43/* Functions */
50const char * get_codec_filename(int cod_spec); 44const char * get_codec_filename(int cod_spec);
51void voice_wait(void); 45void voice_wait(void);
@@ -53,13 +47,7 @@ void voice_wait(void);
53#if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */ 47#if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */
54extern void audio_next_dir(void); 48extern void audio_next_dir(void);
55extern void audio_prev_dir(void); 49extern void audio_prev_dir(void);
56void playback_add_event(enum PLAYBACK_EVENT_TYPE type, void (*handler));
57void playback_remove_event(enum PLAYBACK_EVENT_TYPE type, void (*handler));
58#else 50#else
59/* Really, should get rid of these HWCODEC api definitions here. */
60void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3));
61void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3));
62void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3));
63# define audio_next_dir() 51# define audio_next_dir()
64#define audio_prev_dir() 52#define audio_prev_dir()
65#endif 53#endif
diff --git a/apps/scrobbler.c b/apps/scrobbler.c
index 16869bf18f..2f60e858e1 100644
--- a/apps/scrobbler.c
+++ b/apps/scrobbler.c
@@ -183,7 +183,10 @@ static void add_to_cache(unsigned long play_length)
183 } else { 183 } else {
184 cache_pos++; 184 cache_pos++;
185 if (!scrobbler_ata_callback) 185 if (!scrobbler_ata_callback)
186 scrobbler_ata_callback = register_ata_idle_func(scrobbler_flush_callback); 186 {
187 register_ata_idle_func(scrobbler_flush_callback);
188 scrobbler_ata_callback = true;
189 }
187 } 190 }
188 191
189} 192}
@@ -224,11 +227,7 @@ int scrobbler_init(void)
224 227
225 scrobbler_cache = buffer_alloc(SCROBBLER_MAX_CACHE*SCROBBLER_CACHE_LEN); 228 scrobbler_cache = buffer_alloc(SCROBBLER_MAX_CACHE*SCROBBLER_CACHE_LEN);
226 229
227#if CONFIG_CODEC == SWCODEC 230 add_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
228 playback_add_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
229#else
230 audio_set_track_changed_event(&scrobbler_change_event);
231#endif
232 cache_pos = 0; 231 cache_pos = 0;
233 pending = false; 232 pending = false;
234 scrobbler_initialised = true; 233 scrobbler_initialised = true;
@@ -263,11 +262,7 @@ void scrobbler_shutdown(void)
263 262
264 if (scrobbler_initialised) 263 if (scrobbler_initialised)
265 { 264 {
266#if CONFIG_CODEC == SWCODEC 265 remove_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
267 playback_remove_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
268#else
269 audio_set_track_changed_event(NULL);
270#endif
271 scrobbler_initialised = false; 266 scrobbler_initialised = false;
272 } 267 }
273} 268}
diff --git a/apps/settings.c b/apps/settings.c
index 27832b427f..7eec15baf3 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -601,25 +601,7 @@ int settings_save( void )
601 target doesnt have rtc ram */ 601 target doesnt have rtc ram */
602 write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE); 602 write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
603#endif 603#endif
604 if(!register_ata_idle_func(flush_config_block_callback)) 604 register_ata_idle_func(flush_config_block_callback);
605 {
606 int i;
607 FOR_NB_SCREENS(i)
608 {
609 screens[i].clear_display();
610#ifdef HAVE_LCD_CHARCELLS
611 screens[i].puts(0, 0, str(LANG_SETTINGS_SAVE_FAILED));
612 screens[i].puts(0, 1, str(LANG_SETTINGS_PARTITION));
613#else
614 screens[i].puts(4, 2, str(LANG_SETTINGS_SAVE_FAILED));
615 screens[i].puts(2, 4, str(LANG_SETTINGS_PARTITION));
616 screens[i].update();
617#endif
618 }
619 cond_talk_ids_fq(LANG_SETTINGS_SAVE_FAILED);
620 sleep(HZ*2);
621 return -1;
622 }
623 return 0; 605 return 0;
624} 606}
625bool settings_save_config(int options) 607bool settings_save_config(int options)
diff --git a/apps/tagtree.c b/apps/tagtree.c
index c5e3ebff1e..4572204ae5 100644
--- a/apps/tagtree.c
+++ b/apps/tagtree.c
@@ -924,14 +924,9 @@ void tagtree_init(void)
924 root_menu = 0; 924 root_menu = 0;
925 925
926 uniqbuf = buffer_alloc(UNIQBUF_SIZE); 926 uniqbuf = buffer_alloc(UNIQBUF_SIZE);
927#if CONFIG_CODEC == SWCODEC 927
928 playback_add_event(PLAYBACK_EVENT_TRACK_BUFFER, tagtree_buffer_event); 928 add_event(PLAYBACK_EVENT_TRACK_BUFFER, tagtree_buffer_event);
929 playback_add_event(PLAYBACK_EVENT_TRACK_FINISH, tagtree_track_finish_event); 929 add_event(PLAYBACK_EVENT_TRACK_FINISH, tagtree_track_finish_event);
930#else
931 audio_set_track_buffer_event(tagtree_buffer_event);
932 audio_set_track_unbuffer_event(tagtree_track_finish_event);
933#endif
934
935} 930}
936 931
937static bool show_search_progress(bool init, int count) 932static bool show_search_progress(bool init, int count)
diff --git a/firmware/SOURCES b/firmware/SOURCES
index b5906d4648..ea8ce46cca 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -1,4 +1,5 @@
1ata_idle_notify.c 1ata_idle_notify.c
2events.c
2backlight.c 3backlight.c
3buffer.c 4buffer.c
4id3.c 5id3.c
diff --git a/firmware/ata_idle_notify.c b/firmware/ata_idle_notify.c
index 1fc6605ac6..a97c3538da 100644
--- a/firmware/ata_idle_notify.c
+++ b/firmware/ata_idle_notify.c
@@ -23,60 +23,31 @@
23#include "kernel.h" 23#include "kernel.h"
24#include "string.h" 24#include "string.h"
25 25
26#if USING_ATA_CALLBACK 26void register_ata_idle_func(ata_idle_notify function)
27static ata_idle_notify ata_idle_notify_funcs[MAX_ATA_CALLBACKS];
28static int ata_callback_count = 0;
29#endif
30
31
32bool register_ata_idle_func(ata_idle_notify function)
33{ 27{
34#if USING_ATA_CALLBACK 28#if USING_ATA_CALLBACK
35 int i; 29 add_event(DISK_EVENT_SPINUP, function);
36 if (ata_callback_count >= MAX_ATA_CALLBACKS)
37 return false;
38 for (i=0; i<MAX_ATA_CALLBACKS; i++)
39 {
40 if (ata_idle_notify_funcs[i] == NULL)
41 {
42 ata_idle_notify_funcs[i] = function;
43 ata_callback_count++;
44 return true;
45 }
46 else if (ata_idle_notify_funcs[i] == function)
47 return true;
48 }
49 return false;
50#else 30#else
51 function(); /* just call the function now */ 31 function(); /* just call the function now */
52/* this _may_ cause problems later if the calling function 32/* this _may_ cause problems later if the calling function
53 sets a variable expecting the callback to unset it, because 33 sets a variable expecting the callback to unset it, because
54 the callback will be run before this function exits, so before the var is set */ 34 the callback will be run before this function exits, so before the var is set */
55 return true;
56#endif 35#endif
57} 36}
58 37
59#if USING_ATA_CALLBACK 38#if USING_ATA_CALLBACK
60void unregister_ata_idle_func(ata_idle_notify func, bool run) 39void unregister_ata_idle_func(ata_idle_notify func, bool run)
61{ 40{
62 int i; 41 remove_event(DISK_EVENT_SPINUP, func);
63 for (i=0; i<MAX_ATA_CALLBACKS; i++) 42
64 { 43 if (run)
65 if (ata_idle_notify_funcs[i] == func) 44 func();
66 {
67 ata_idle_notify_funcs[i] = NULL;
68 ata_callback_count--;
69 if (run) func();
70 }
71 }
72 return;
73} 45}
74 46
75bool call_ata_idle_notifys(bool force) 47bool call_ata_idle_notifys(bool force)
76{ 48{
77 int i;
78 static int lock_until = 0; 49 static int lock_until = 0;
79 ata_idle_notify function; 50
80 if (!force) 51 if (!force)
81 { 52 {
82 if (TIME_BEFORE(current_tick,lock_until) ) 53 if (TIME_BEFORE(current_tick,lock_until) )
@@ -84,22 +55,8 @@ bool call_ata_idle_notifys(bool force)
84 } 55 }
85 lock_until = current_tick + 30*HZ; 56 lock_until = current_tick + 30*HZ;
86 57
87 for (i = 0; i < MAX_ATA_CALLBACKS; i++) 58 send_event(DISK_EVENT_SPINUP, true, NULL);
88 { 59
89 if (ata_idle_notify_funcs[i])
90 {
91 function = ata_idle_notify_funcs[i];
92 ata_idle_notify_funcs[i] = NULL;
93 function();
94 ata_callback_count--;
95 }
96 }
97 return true; 60 return true;
98} 61}
99
100void ata_idle_notify_init(void)
101{
102 ata_callback_count = 0;
103 memset(ata_idle_notify_funcs, 0, sizeof(ata_idle_notify_funcs));
104}
105#endif 62#endif
diff --git a/firmware/events.c b/firmware/events.c
new file mode 100644
index 0000000000..eaf2e5c352
--- /dev/null
+++ b/firmware/events.c
@@ -0,0 +1,88 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Miika Pekkarinen
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <stdio.h>
21#include "events.h"
22#include "panic.h"
23
24struct sysevent {
25 unsigned short id;
26 void (*callback)(void *data);
27};
28
29struct sysevent events[MAX_SYS_EVENTS];
30
31bool add_event(unsigned short id, void (*handler))
32{
33 int i;
34
35 /* Chcek if the event already exists. */
36 for (i = 0; i < MAX_SYS_EVENTS; i++)
37 {
38 if (events[i].callback == handler && events[i].id == id)
39 return false;
40 }
41
42 /* Try to find a free slot. */
43 for (i = 0; i < MAX_SYS_EVENTS; i++)
44 {
45 if (events[i].callback == NULL)
46 {
47 events[i].id = id;
48 events[i].callback = handler;
49 return true;
50 }
51 }
52
53 panicf("event line full");
54 return false;
55}
56
57void remove_event(unsigned short id, void (*handler))
58{
59 int i;
60
61 for (i = 0; i < MAX_SYS_EVENTS; i++)
62 {
63 if (events[i].id == id && events[i].callback == handler)
64 {
65 events[i].callback = NULL;
66 return;
67 }
68 }
69
70 panicf("event not found");
71}
72
73void send_event(unsigned short id, bool oneshot, void *data)
74{
75 int i;
76
77 for (i = 0; i < MAX_SYS_EVENTS; i++)
78 {
79 if (events[i].id == id && events[i].callback != NULL)
80 {
81 events[i].callback(data);
82
83 if (oneshot)
84 events[i].callback = NULL;
85 }
86 }
87}
88
diff --git a/firmware/export/ata_idle_notify.h b/firmware/export/ata_idle_notify.h
index ee825c967e..1dda3e196a 100644
--- a/firmware/export/ata_idle_notify.h
+++ b/firmware/export/ata_idle_notify.h
@@ -19,7 +19,9 @@
19#ifndef __ATACALLBACK_H__ 19#ifndef __ATACALLBACK_H__
20#define __ATACALLBACK_H__ 20#define __ATACALLBACK_H__
21 21
22
22#include <stdbool.h> 23#include <stdbool.h>
24#include "events.h"
23 25
24#if 0 26#if 0
25 NOTE: ata_idle_nofity usage notes.. 27 NOTE: ata_idle_nofity usage notes..
@@ -34,15 +36,17 @@
34 5) Dont Panic! 36 5) Dont Panic!
35#endif 37#endif
36 38
39enum {
40 DISK_EVENT_SPINUP = (EVENT_CLASS_DISK|1),
41};
42
37#define USING_ATA_CALLBACK !defined(SIMULATOR) \ 43#define USING_ATA_CALLBACK !defined(SIMULATOR) \
38 && !defined(HAVE_FLASH_DISK) 44 && !defined(HAVE_FLASH_DISK)
39 45
40#define MAX_ATA_CALLBACKS 5
41typedef bool (*ata_idle_notify)(void); 46typedef bool (*ata_idle_notify)(void);
42 47
43extern bool register_ata_idle_func(ata_idle_notify function); 48extern void register_ata_idle_func(ata_idle_notify function);
44#if USING_ATA_CALLBACK 49#if USING_ATA_CALLBACK
45extern void ata_idle_notify_init(void);
46extern void unregister_ata_idle_func(ata_idle_notify function, bool run); 50extern void unregister_ata_idle_func(ata_idle_notify function, bool run);
47extern bool call_ata_idle_notifys(bool force); 51extern bool call_ata_idle_notifys(bool force);
48#else 52#else
diff --git a/firmware/export/events.h b/firmware/export/events.h
new file mode 100644
index 0000000000..b27b5dee4c
--- /dev/null
+++ b/firmware/export/events.h
@@ -0,0 +1,51 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Miika Pekkarinen
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef _EVENTS_H
21#define _EVENTS_H
22
23#include <stdbool.h>
24
25#define MAX_SYS_EVENTS 10
26
27/**
28 * High nibble = Event class definition
29 * Low nibble = Event ID
30 */
31
32#define EVENT_CLASS_DISK 0x0100
33#define EVENT_CLASS_PLAYBACK 0x0200
34
35/**
36 * Because same playback events are used in mpeg.c and playback.c, define
37 * them here to prevent cluttering and ifdefs.
38 */
39enum {
40 PLAYBACK_EVENT_TRACK_BUFFER = (EVENT_CLASS_PLAYBACK|1),
41 PLAYBACK_EVENT_TRACK_FINISH,
42 PLAYBACK_EVENT_TRACK_CHANGE,
43};
44
45
46bool add_event(unsigned short id, void (*handler));
47void remove_event(unsigned short id, void (*handler));
48void send_event(unsigned short id, bool oneshot, void *data);
49
50#endif
51
diff --git a/firmware/export/mpeg.h b/firmware/export/mpeg.h
index 3e36c44ac5..0a9d62cdf0 100644
--- a/firmware/export/mpeg.h
+++ b/firmware/export/mpeg.h
@@ -21,6 +21,7 @@
21 21
22#include <stdbool.h> 22#include <stdbool.h>
23#include "id3.h" 23#include "id3.h"
24#include "events.h"
24 25
25#define MPEG_SWAP_CHUNKSIZE 0x2000 26#define MPEG_SWAP_CHUNKSIZE 0x2000
26#define MPEG_HIGH_WATER 2 /* We leave 2 bytes empty because otherwise we 27#define MPEG_HIGH_WATER 2 /* We leave 2 bytes empty because otherwise we
diff --git a/firmware/mpeg.c b/firmware/mpeg.c
index 693e2df480..9023c304d2 100644
--- a/firmware/mpeg.c
+++ b/firmware/mpeg.c
@@ -100,7 +100,6 @@ struct trackdata
100 struct mp3entry id3; 100 struct mp3entry id3;
101 int mempos; 101 int mempos;
102 int load_ahead_index; 102 int load_ahead_index;
103 bool event_sent;
104}; 103};
105 104
106static struct trackdata trackdata[MAX_TRACK_ENTRIES]; 105static struct trackdata trackdata[MAX_TRACK_ENTRIES];
@@ -116,11 +115,6 @@ static int track_read_idx = 0;
116static int track_write_idx = 0; 115static int track_write_idx = 0;
117#endif /* !SIMULATOR */ 116#endif /* !SIMULATOR */
118 117
119/* Callback function to call when current track has really changed. */
120void (*track_changed_callback)(struct mp3entry *id3) = NULL;
121void (*track_buffer_callback)(struct mp3entry *id3) = NULL;
122void (*track_unbuffer_callback)(struct mp3entry *id3) = NULL;
123
124/* Cuesheet callback */ 118/* Cuesheet callback */
125static bool (*cuesheet_callback)(const char *filename) = NULL; 119static bool (*cuesheet_callback)(const char *filename) = NULL;
126 120
@@ -475,21 +469,6 @@ unsigned long mpeg_get_last_header(void)
475#endif /* !SIMULATOR */ 469#endif /* !SIMULATOR */
476} 470}
477 471
478void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3))
479{
480 track_buffer_callback = handler;
481}
482
483void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3))
484{
485 track_unbuffer_callback = handler;
486}
487
488void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
489{
490 track_changed_callback = handler;
491}
492
493void audio_set_cuesheet_callback(bool (*handler)(const char *filename)) 472void audio_set_cuesheet_callback(bool (*handler)(const char *filename))
494{ 473{
495 cuesheet_callback = handler; 474 cuesheet_callback = handler;
@@ -506,12 +485,7 @@ static void generate_unbuffer_events(void)
506 for (i = 0; i < numentries; i++) 485 for (i = 0; i < numentries; i++)
507 { 486 {
508 /* Send an event to notify that track has finished. */ 487 /* Send an event to notify that track has finished. */
509 if (trackdata[cur_idx].event_sent) 488 send_event(PLAYBACK_EVENT_TRACK_FINISH, false, &trackdata[cur_idx].id3);
510 {
511 if (track_unbuffer_callback)
512 track_unbuffer_callback(&trackdata[cur_idx].id3);
513 trackdata[cur_idx].event_sent = false;
514 }
515 cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK; 489 cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK;
516 } 490 }
517} 491}
@@ -525,12 +499,7 @@ static void generate_postbuffer_events(void)
525 499
526 for (i = 0; i < numentries; i++) 500 for (i = 0; i < numentries; i++)
527 { 501 {
528 if (!trackdata[cur_idx].event_sent) 502 send_event(PLAYBACK_EVENT_TRACK_BUFFER, false, &trackdata[cur_idx].id3);
529 {
530 if (track_buffer_callback)
531 track_buffer_callback(&trackdata[cur_idx].id3);
532 trackdata[cur_idx].event_sent = true;
533 }
534 cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK; 503 cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK;
535 } 504 }
536} 505}
@@ -1080,8 +1049,7 @@ static void track_change(void)
1080 if (num_tracks_in_memory() > 0) 1049 if (num_tracks_in_memory() > 0)
1081 { 1050 {
1082 remove_current_tag(); 1051 remove_current_tag();
1083 if (track_changed_callback) 1052 send_event(PLAYBACK_EVENT_TRACK_CHANGE, false, audio_current_track());
1084 track_changed_callback(audio_current_track());
1085 update_playlist(); 1053 update_playlist();
1086 } 1054 }
1087 1055
@@ -1134,8 +1102,7 @@ static void start_playback_if_ready(void)
1134 if (play_pending_track_change) 1102 if (play_pending_track_change)
1135 { 1103 {
1136 play_pending_track_change = false; 1104 play_pending_track_change = false;
1137 if(track_changed_callback) 1105 send_event(PLAYBACK_EVENT_TRACK_CHANGE, false, audio_current_track());
1138 track_changed_callback(audio_current_track());
1139 } 1106 }
1140 play_pending = false; 1107 play_pending = false;
1141 } 1108 }