mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-12-09 21:25:19 -05:00
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
This commit is contained in:
parent
478ba0afa1
commit
19c6e66c13
14 changed files with 182 additions and 209 deletions
|
|
@ -8191,29 +8191,27 @@
|
||||||
</phrase>
|
</phrase>
|
||||||
<phrase>
|
<phrase>
|
||||||
id: LANG_SETTINGS_SAVE_FAILED
|
id: LANG_SETTINGS_SAVE_FAILED
|
||||||
desc: displayed if save settings has failed
|
desc: DEPRECATED
|
||||||
user:
|
user:
|
||||||
<source>
|
<source>
|
||||||
*: "Save Failed"
|
*: ""
|
||||||
</source>
|
</source>
|
||||||
<dest>
|
<dest>
|
||||||
*: "Save Failed"
|
*: ""
|
||||||
</dest>
|
</dest>
|
||||||
<voice>
|
<voice>
|
||||||
*: "Save Failed"
|
*: ""
|
||||||
</voice>
|
</voice>
|
||||||
</phrase>
|
</phrase>
|
||||||
<phrase>
|
<phrase>
|
||||||
id: LANG_SETTINGS_PARTITION
|
id: LANG_SETTINGS_PARTITION
|
||||||
desc: if save settings has failed
|
desc: DEPRECATED
|
||||||
user:
|
user:
|
||||||
<source>
|
<source>
|
||||||
*: "No partition?"
|
*: ""
|
||||||
player: "Partition?"
|
|
||||||
</source>
|
</source>
|
||||||
<dest>
|
<dest>
|
||||||
*: "No partition?"
|
*: ""
|
||||||
player: "Partition?"
|
|
||||||
</dest>
|
</dest>
|
||||||
<voice>
|
<voice>
|
||||||
*: ""
|
*: ""
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,6 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include "ata.h"
|
#include "ata.h"
|
||||||
#include "ata_idle_notify.h"
|
|
||||||
#include "disk.h"
|
#include "disk.h"
|
||||||
#include "fat.h"
|
#include "fat.h"
|
||||||
#include "lcd.h"
|
#include "lcd.h"
|
||||||
|
|
@ -428,7 +427,6 @@ static void init(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ata_idle_notify_init();
|
|
||||||
rc = ata_init();
|
rc = ata_init();
|
||||||
if(rc)
|
if(rc)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -245,13 +245,6 @@ static bool skipped_during_pause = false; /* Do we need to clear the PCM buffer
|
||||||
*/
|
*/
|
||||||
static bool codec_requested_stop = false;
|
static bool codec_requested_stop = false;
|
||||||
|
|
||||||
struct playback_event {
|
|
||||||
enum PLAYBACK_EVENT_TYPE type;
|
|
||||||
void (*callback)(void *data);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct playback_event events[PLAYBACK_MAX_EVENTS];
|
|
||||||
|
|
||||||
static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
|
static size_t buffer_margin = 0; /* Buffer margin aka anti-skip buffer (A/C-) */
|
||||||
|
|
||||||
/* Multiple threads */
|
/* Multiple threads */
|
||||||
|
|
@ -1447,51 +1440,6 @@ static void codec_thread(void)
|
||||||
|
|
||||||
/* --- Audio thread --- */
|
/* --- Audio thread --- */
|
||||||
|
|
||||||
void playback_add_event(enum PLAYBACK_EVENT_TYPE type, void (*handler))
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
/* Try to find a free slot. */
|
|
||||||
for (i = 0; i < PLAYBACK_MAX_EVENTS; i++)
|
|
||||||
{
|
|
||||||
if (events[i].callback == NULL)
|
|
||||||
{
|
|
||||||
events[i].type = type;
|
|
||||||
events[i].callback = handler;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
panicf("playback event line full");
|
|
||||||
}
|
|
||||||
|
|
||||||
void playback_remove_event(enum PLAYBACK_EVENT_TYPE type, void (*handler))
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < PLAYBACK_MAX_EVENTS; i++)
|
|
||||||
{
|
|
||||||
if (events[i].type == type && events[i].callback == handler)
|
|
||||||
{
|
|
||||||
events[i].callback = NULL;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
panicf("playback event not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void send_event(enum PLAYBACK_EVENT_TYPE type, void *data)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < PLAYBACK_MAX_EVENTS; i++)
|
|
||||||
{
|
|
||||||
if (events[i].type == type && events[i].callback != NULL)
|
|
||||||
events[i].callback(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool audio_have_tracks(void)
|
static bool audio_have_tracks(void)
|
||||||
{
|
{
|
||||||
return (audio_track_count() != 0);
|
return (audio_track_count() != 0);
|
||||||
|
|
@ -1783,7 +1731,7 @@ static bool audio_load_track(int offset, bool start_play)
|
||||||
{
|
{
|
||||||
if (get_metadata(&id3, fd, trackname))
|
if (get_metadata(&id3, fd, trackname))
|
||||||
{
|
{
|
||||||
send_event(PLAYBACK_EVENT_TRACK_BUFFER, &id3);
|
send_event(PLAYBACK_EVENT_TRACK_BUFFER, false, &id3);
|
||||||
|
|
||||||
tracks[track_widx].id3_hid =
|
tracks[track_widx].id3_hid =
|
||||||
bufalloc(&id3, sizeof(struct mp3entry), TYPE_ID3);
|
bufalloc(&id3, sizeof(struct mp3entry), TYPE_ID3);
|
||||||
|
|
@ -2020,7 +1968,7 @@ static int audio_check_new_track(void)
|
||||||
bool end_of_playlist; /* Temporary flag, not the same as playlist_end */
|
bool end_of_playlist; /* Temporary flag, not the same as playlist_end */
|
||||||
|
|
||||||
/* Now it's good time to send track unbuffer events. */
|
/* Now it's good time to send track unbuffer events. */
|
||||||
send_event(PLAYBACK_EVENT_TRACK_FINISH, &curtrack_id3);
|
send_event(PLAYBACK_EVENT_TRACK_FINISH, false, &curtrack_id3);
|
||||||
|
|
||||||
if (dir_skip)
|
if (dir_skip)
|
||||||
{
|
{
|
||||||
|
|
@ -2391,7 +2339,7 @@ static void audio_finalise_track_change(void)
|
||||||
bufgetid3(prev_ti->id3_hid)->elapsed = 0;
|
bufgetid3(prev_ti->id3_hid)->elapsed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
send_event(PLAYBACK_EVENT_TRACK_CHANGE, &curtrack_id3);
|
send_event(PLAYBACK_EVENT_TRACK_CHANGE, false, &curtrack_id3);
|
||||||
|
|
||||||
track_changed = true;
|
track_changed = true;
|
||||||
playlist_update_resume_info(audio_current_track());
|
playlist_update_resume_info(audio_current_track());
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include "id3.h"
|
#include "id3.h"
|
||||||
#include "mp3data.h"
|
#include "mp3data.h"
|
||||||
|
#include "events.h"
|
||||||
|
|
||||||
#define CODEC_IDX_AUDIO 0
|
#define CODEC_IDX_AUDIO 0
|
||||||
#define CODEC_IDX_VOICE 1
|
#define CODEC_IDX_VOICE 1
|
||||||
|
|
@ -39,13 +40,6 @@
|
||||||
|
|
||||||
#define MAX_TRACK_MASK (MAX_TRACK-1)
|
#define MAX_TRACK_MASK (MAX_TRACK-1)
|
||||||
|
|
||||||
#define PLAYBACK_MAX_EVENTS 4
|
|
||||||
enum PLAYBACK_EVENT_TYPE {
|
|
||||||
PLAYBACK_EVENT_TRACK_BUFFER,
|
|
||||||
PLAYBACK_EVENT_TRACK_FINISH,
|
|
||||||
PLAYBACK_EVENT_TRACK_CHANGE,
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
const char * get_codec_filename(int cod_spec);
|
const char * get_codec_filename(int cod_spec);
|
||||||
void voice_wait(void);
|
void voice_wait(void);
|
||||||
|
|
@ -53,13 +47,7 @@ void voice_wait(void);
|
||||||
#if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */
|
#if CONFIG_CODEC == SWCODEC /* This #ifdef is better here than gui/gwps.c */
|
||||||
extern void audio_next_dir(void);
|
extern void audio_next_dir(void);
|
||||||
extern void audio_prev_dir(void);
|
extern void audio_prev_dir(void);
|
||||||
void playback_add_event(enum PLAYBACK_EVENT_TYPE type, void (*handler));
|
|
||||||
void playback_remove_event(enum PLAYBACK_EVENT_TYPE type, void (*handler));
|
|
||||||
#else
|
#else
|
||||||
/* Really, should get rid of these HWCODEC api definitions here. */
|
|
||||||
void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3));
|
|
||||||
void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3));
|
|
||||||
void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3));
|
|
||||||
# define audio_next_dir()
|
# define audio_next_dir()
|
||||||
#define audio_prev_dir()
|
#define audio_prev_dir()
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,10 @@ static void add_to_cache(unsigned long play_length)
|
||||||
} else {
|
} else {
|
||||||
cache_pos++;
|
cache_pos++;
|
||||||
if (!scrobbler_ata_callback)
|
if (!scrobbler_ata_callback)
|
||||||
scrobbler_ata_callback = register_ata_idle_func(scrobbler_flush_callback);
|
{
|
||||||
|
register_ata_idle_func(scrobbler_flush_callback);
|
||||||
|
scrobbler_ata_callback = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -224,11 +227,7 @@ int scrobbler_init(void)
|
||||||
|
|
||||||
scrobbler_cache = buffer_alloc(SCROBBLER_MAX_CACHE*SCROBBLER_CACHE_LEN);
|
scrobbler_cache = buffer_alloc(SCROBBLER_MAX_CACHE*SCROBBLER_CACHE_LEN);
|
||||||
|
|
||||||
#if CONFIG_CODEC == SWCODEC
|
add_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
|
||||||
playback_add_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
|
|
||||||
#else
|
|
||||||
audio_set_track_changed_event(&scrobbler_change_event);
|
|
||||||
#endif
|
|
||||||
cache_pos = 0;
|
cache_pos = 0;
|
||||||
pending = false;
|
pending = false;
|
||||||
scrobbler_initialised = true;
|
scrobbler_initialised = true;
|
||||||
|
|
@ -263,11 +262,7 @@ void scrobbler_shutdown(void)
|
||||||
|
|
||||||
if (scrobbler_initialised)
|
if (scrobbler_initialised)
|
||||||
{
|
{
|
||||||
#if CONFIG_CODEC == SWCODEC
|
remove_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
|
||||||
playback_remove_event(PLAYBACK_EVENT_TRACK_CHANGE, scrobbler_change_event);
|
|
||||||
#else
|
|
||||||
audio_set_track_changed_event(NULL);
|
|
||||||
#endif
|
|
||||||
scrobbler_initialised = false;
|
scrobbler_initialised = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -601,25 +601,7 @@ int settings_save( void )
|
||||||
target doesnt have rtc ram */
|
target doesnt have rtc ram */
|
||||||
write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
|
write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
|
||||||
#endif
|
#endif
|
||||||
if(!register_ata_idle_func(flush_config_block_callback))
|
register_ata_idle_func(flush_config_block_callback);
|
||||||
{
|
|
||||||
int i;
|
|
||||||
FOR_NB_SCREENS(i)
|
|
||||||
{
|
|
||||||
screens[i].clear_display();
|
|
||||||
#ifdef HAVE_LCD_CHARCELLS
|
|
||||||
screens[i].puts(0, 0, str(LANG_SETTINGS_SAVE_FAILED));
|
|
||||||
screens[i].puts(0, 1, str(LANG_SETTINGS_PARTITION));
|
|
||||||
#else
|
|
||||||
screens[i].puts(4, 2, str(LANG_SETTINGS_SAVE_FAILED));
|
|
||||||
screens[i].puts(2, 4, str(LANG_SETTINGS_PARTITION));
|
|
||||||
screens[i].update();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
cond_talk_ids_fq(LANG_SETTINGS_SAVE_FAILED);
|
|
||||||
sleep(HZ*2);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
bool settings_save_config(int options)
|
bool settings_save_config(int options)
|
||||||
|
|
|
||||||
|
|
@ -924,14 +924,9 @@ void tagtree_init(void)
|
||||||
root_menu = 0;
|
root_menu = 0;
|
||||||
|
|
||||||
uniqbuf = buffer_alloc(UNIQBUF_SIZE);
|
uniqbuf = buffer_alloc(UNIQBUF_SIZE);
|
||||||
#if CONFIG_CODEC == SWCODEC
|
|
||||||
playback_add_event(PLAYBACK_EVENT_TRACK_BUFFER, tagtree_buffer_event);
|
add_event(PLAYBACK_EVENT_TRACK_BUFFER, tagtree_buffer_event);
|
||||||
playback_add_event(PLAYBACK_EVENT_TRACK_FINISH, tagtree_track_finish_event);
|
add_event(PLAYBACK_EVENT_TRACK_FINISH, tagtree_track_finish_event);
|
||||||
#else
|
|
||||||
audio_set_track_buffer_event(tagtree_buffer_event);
|
|
||||||
audio_set_track_unbuffer_event(tagtree_track_finish_event);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool show_search_progress(bool init, int count)
|
static bool show_search_progress(bool init, int count)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
ata_idle_notify.c
|
ata_idle_notify.c
|
||||||
|
events.c
|
||||||
backlight.c
|
backlight.c
|
||||||
buffer.c
|
buffer.c
|
||||||
id3.c
|
id3.c
|
||||||
|
|
|
||||||
|
|
@ -23,60 +23,31 @@
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
|
||||||
#if USING_ATA_CALLBACK
|
void register_ata_idle_func(ata_idle_notify function)
|
||||||
static ata_idle_notify ata_idle_notify_funcs[MAX_ATA_CALLBACKS];
|
|
||||||
static int ata_callback_count = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
bool register_ata_idle_func(ata_idle_notify function)
|
|
||||||
{
|
{
|
||||||
#if USING_ATA_CALLBACK
|
#if USING_ATA_CALLBACK
|
||||||
int i;
|
add_event(DISK_EVENT_SPINUP, function);
|
||||||
if (ata_callback_count >= MAX_ATA_CALLBACKS)
|
|
||||||
return false;
|
|
||||||
for (i=0; i<MAX_ATA_CALLBACKS; i++)
|
|
||||||
{
|
|
||||||
if (ata_idle_notify_funcs[i] == NULL)
|
|
||||||
{
|
|
||||||
ata_idle_notify_funcs[i] = function;
|
|
||||||
ata_callback_count++;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (ata_idle_notify_funcs[i] == function)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
#else
|
#else
|
||||||
function(); /* just call the function now */
|
function(); /* just call the function now */
|
||||||
/* this _may_ cause problems later if the calling function
|
/* this _may_ cause problems later if the calling function
|
||||||
sets a variable expecting the callback to unset it, because
|
sets a variable expecting the callback to unset it, because
|
||||||
the callback will be run before this function exits, so before the var is set */
|
the callback will be run before this function exits, so before the var is set */
|
||||||
return true;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if USING_ATA_CALLBACK
|
#if USING_ATA_CALLBACK
|
||||||
void unregister_ata_idle_func(ata_idle_notify func, bool run)
|
void unregister_ata_idle_func(ata_idle_notify func, bool run)
|
||||||
{
|
{
|
||||||
int i;
|
remove_event(DISK_EVENT_SPINUP, func);
|
||||||
for (i=0; i<MAX_ATA_CALLBACKS; i++)
|
|
||||||
{
|
if (run)
|
||||||
if (ata_idle_notify_funcs[i] == func)
|
func();
|
||||||
{
|
|
||||||
ata_idle_notify_funcs[i] = NULL;
|
|
||||||
ata_callback_count--;
|
|
||||||
if (run) func();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool call_ata_idle_notifys(bool force)
|
bool call_ata_idle_notifys(bool force)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
static int lock_until = 0;
|
static int lock_until = 0;
|
||||||
ata_idle_notify function;
|
|
||||||
if (!force)
|
if (!force)
|
||||||
{
|
{
|
||||||
if (TIME_BEFORE(current_tick,lock_until) )
|
if (TIME_BEFORE(current_tick,lock_until) )
|
||||||
|
|
@ -84,22 +55,8 @@ bool call_ata_idle_notifys(bool force)
|
||||||
}
|
}
|
||||||
lock_until = current_tick + 30*HZ;
|
lock_until = current_tick + 30*HZ;
|
||||||
|
|
||||||
for (i = 0; i < MAX_ATA_CALLBACKS; i++)
|
send_event(DISK_EVENT_SPINUP, true, NULL);
|
||||||
{
|
|
||||||
if (ata_idle_notify_funcs[i])
|
|
||||||
{
|
|
||||||
function = ata_idle_notify_funcs[i];
|
|
||||||
ata_idle_notify_funcs[i] = NULL;
|
|
||||||
function();
|
|
||||||
ata_callback_count--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ata_idle_notify_init(void)
|
|
||||||
{
|
|
||||||
ata_callback_count = 0;
|
|
||||||
memset(ata_idle_notify_funcs, 0, sizeof(ata_idle_notify_funcs));
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
88
firmware/events.c
Normal file
88
firmware/events.c
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 by Miika Pekkarinen
|
||||||
|
*
|
||||||
|
* All files in this archive are subject to the GNU General Public License.
|
||||||
|
* See the file COPYING in the source tree root for full license agreement.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "events.h"
|
||||||
|
#include "panic.h"
|
||||||
|
|
||||||
|
struct sysevent {
|
||||||
|
unsigned short id;
|
||||||
|
void (*callback)(void *data);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sysevent events[MAX_SYS_EVENTS];
|
||||||
|
|
||||||
|
bool add_event(unsigned short id, void (*handler))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Chcek if the event already exists. */
|
||||||
|
for (i = 0; i < MAX_SYS_EVENTS; i++)
|
||||||
|
{
|
||||||
|
if (events[i].callback == handler && events[i].id == id)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Try to find a free slot. */
|
||||||
|
for (i = 0; i < MAX_SYS_EVENTS; i++)
|
||||||
|
{
|
||||||
|
if (events[i].callback == NULL)
|
||||||
|
{
|
||||||
|
events[i].id = id;
|
||||||
|
events[i].callback = handler;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panicf("event line full");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove_event(unsigned short id, void (*handler))
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_SYS_EVENTS; i++)
|
||||||
|
{
|
||||||
|
if (events[i].id == id && events[i].callback == handler)
|
||||||
|
{
|
||||||
|
events[i].callback = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panicf("event not found");
|
||||||
|
}
|
||||||
|
|
||||||
|
void send_event(unsigned short id, bool oneshot, void *data)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_SYS_EVENTS; i++)
|
||||||
|
{
|
||||||
|
if (events[i].id == id && events[i].callback != NULL)
|
||||||
|
{
|
||||||
|
events[i].callback(data);
|
||||||
|
|
||||||
|
if (oneshot)
|
||||||
|
events[i].callback = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -19,7 +19,9 @@
|
||||||
#ifndef __ATACALLBACK_H__
|
#ifndef __ATACALLBACK_H__
|
||||||
#define __ATACALLBACK_H__
|
#define __ATACALLBACK_H__
|
||||||
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "events.h"
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
NOTE: ata_idle_nofity usage notes..
|
NOTE: ata_idle_nofity usage notes..
|
||||||
|
|
@ -34,15 +36,17 @@
|
||||||
5) Dont Panic!
|
5) Dont Panic!
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
DISK_EVENT_SPINUP = (EVENT_CLASS_DISK|1),
|
||||||
|
};
|
||||||
|
|
||||||
#define USING_ATA_CALLBACK !defined(SIMULATOR) \
|
#define USING_ATA_CALLBACK !defined(SIMULATOR) \
|
||||||
&& !defined(HAVE_FLASH_DISK)
|
&& !defined(HAVE_FLASH_DISK)
|
||||||
|
|
||||||
#define MAX_ATA_CALLBACKS 5
|
|
||||||
typedef bool (*ata_idle_notify)(void);
|
typedef bool (*ata_idle_notify)(void);
|
||||||
|
|
||||||
extern bool register_ata_idle_func(ata_idle_notify function);
|
extern void register_ata_idle_func(ata_idle_notify function);
|
||||||
#if USING_ATA_CALLBACK
|
#if USING_ATA_CALLBACK
|
||||||
extern void ata_idle_notify_init(void);
|
|
||||||
extern void unregister_ata_idle_func(ata_idle_notify function, bool run);
|
extern void unregister_ata_idle_func(ata_idle_notify function, bool run);
|
||||||
extern bool call_ata_idle_notifys(bool force);
|
extern bool call_ata_idle_notifys(bool force);
|
||||||
#else
|
#else
|
||||||
|
|
|
||||||
51
firmware/export/events.h
Normal file
51
firmware/export/events.h
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
/***************************************************************************
|
||||||
|
* __________ __ ___.
|
||||||
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||||
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||||
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||||
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||||
|
* \/ \/ \/ \/ \/
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
* Copyright (C) 2008 by Miika Pekkarinen
|
||||||
|
*
|
||||||
|
* All files in this archive are subject to the GNU General Public License.
|
||||||
|
* See the file COPYING in the source tree root for full license agreement.
|
||||||
|
*
|
||||||
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||||
|
* KIND, either express or implied.
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef _EVENTS_H
|
||||||
|
#define _EVENTS_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define MAX_SYS_EVENTS 10
|
||||||
|
|
||||||
|
/**
|
||||||
|
* High nibble = Event class definition
|
||||||
|
* Low nibble = Event ID
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define EVENT_CLASS_DISK 0x0100
|
||||||
|
#define EVENT_CLASS_PLAYBACK 0x0200
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Because same playback events are used in mpeg.c and playback.c, define
|
||||||
|
* them here to prevent cluttering and ifdefs.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
PLAYBACK_EVENT_TRACK_BUFFER = (EVENT_CLASS_PLAYBACK|1),
|
||||||
|
PLAYBACK_EVENT_TRACK_FINISH,
|
||||||
|
PLAYBACK_EVENT_TRACK_CHANGE,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
bool add_event(unsigned short id, void (*handler));
|
||||||
|
void remove_event(unsigned short id, void (*handler));
|
||||||
|
void send_event(unsigned short id, bool oneshot, void *data);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "id3.h"
|
#include "id3.h"
|
||||||
|
#include "events.h"
|
||||||
|
|
||||||
#define MPEG_SWAP_CHUNKSIZE 0x2000
|
#define MPEG_SWAP_CHUNKSIZE 0x2000
|
||||||
#define MPEG_HIGH_WATER 2 /* We leave 2 bytes empty because otherwise we
|
#define MPEG_HIGH_WATER 2 /* We leave 2 bytes empty because otherwise we
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,6 @@ struct trackdata
|
||||||
struct mp3entry id3;
|
struct mp3entry id3;
|
||||||
int mempos;
|
int mempos;
|
||||||
int load_ahead_index;
|
int load_ahead_index;
|
||||||
bool event_sent;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct trackdata trackdata[MAX_TRACK_ENTRIES];
|
static struct trackdata trackdata[MAX_TRACK_ENTRIES];
|
||||||
|
|
@ -116,11 +115,6 @@ static int track_read_idx = 0;
|
||||||
static int track_write_idx = 0;
|
static int track_write_idx = 0;
|
||||||
#endif /* !SIMULATOR */
|
#endif /* !SIMULATOR */
|
||||||
|
|
||||||
/* Callback function to call when current track has really changed. */
|
|
||||||
void (*track_changed_callback)(struct mp3entry *id3) = NULL;
|
|
||||||
void (*track_buffer_callback)(struct mp3entry *id3) = NULL;
|
|
||||||
void (*track_unbuffer_callback)(struct mp3entry *id3) = NULL;
|
|
||||||
|
|
||||||
/* Cuesheet callback */
|
/* Cuesheet callback */
|
||||||
static bool (*cuesheet_callback)(const char *filename) = NULL;
|
static bool (*cuesheet_callback)(const char *filename) = NULL;
|
||||||
|
|
||||||
|
|
@ -475,21 +469,6 @@ unsigned long mpeg_get_last_header(void)
|
||||||
#endif /* !SIMULATOR */
|
#endif /* !SIMULATOR */
|
||||||
}
|
}
|
||||||
|
|
||||||
void audio_set_track_buffer_event(void (*handler)(struct mp3entry *id3))
|
|
||||||
{
|
|
||||||
track_buffer_callback = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_set_track_unbuffer_event(void (*handler)(struct mp3entry *id3))
|
|
||||||
{
|
|
||||||
track_unbuffer_callback = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_set_track_changed_event(void (*handler)(struct mp3entry *id3))
|
|
||||||
{
|
|
||||||
track_changed_callback = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
void audio_set_cuesheet_callback(bool (*handler)(const char *filename))
|
void audio_set_cuesheet_callback(bool (*handler)(const char *filename))
|
||||||
{
|
{
|
||||||
cuesheet_callback = handler;
|
cuesheet_callback = handler;
|
||||||
|
|
@ -506,12 +485,7 @@ static void generate_unbuffer_events(void)
|
||||||
for (i = 0; i < numentries; i++)
|
for (i = 0; i < numentries; i++)
|
||||||
{
|
{
|
||||||
/* Send an event to notify that track has finished. */
|
/* Send an event to notify that track has finished. */
|
||||||
if (trackdata[cur_idx].event_sent)
|
send_event(PLAYBACK_EVENT_TRACK_FINISH, false, &trackdata[cur_idx].id3);
|
||||||
{
|
|
||||||
if (track_unbuffer_callback)
|
|
||||||
track_unbuffer_callback(&trackdata[cur_idx].id3);
|
|
||||||
trackdata[cur_idx].event_sent = false;
|
|
||||||
}
|
|
||||||
cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK;
|
cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -525,12 +499,7 @@ static void generate_postbuffer_events(void)
|
||||||
|
|
||||||
for (i = 0; i < numentries; i++)
|
for (i = 0; i < numentries; i++)
|
||||||
{
|
{
|
||||||
if (!trackdata[cur_idx].event_sent)
|
send_event(PLAYBACK_EVENT_TRACK_BUFFER, false, &trackdata[cur_idx].id3);
|
||||||
{
|
|
||||||
if (track_buffer_callback)
|
|
||||||
track_buffer_callback(&trackdata[cur_idx].id3);
|
|
||||||
trackdata[cur_idx].event_sent = true;
|
|
||||||
}
|
|
||||||
cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK;
|
cur_idx = (cur_idx + 1) & MAX_TRACK_ENTRIES_MASK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1080,8 +1049,7 @@ static void track_change(void)
|
||||||
if (num_tracks_in_memory() > 0)
|
if (num_tracks_in_memory() > 0)
|
||||||
{
|
{
|
||||||
remove_current_tag();
|
remove_current_tag();
|
||||||
if (track_changed_callback)
|
send_event(PLAYBACK_EVENT_TRACK_CHANGE, false, audio_current_track());
|
||||||
track_changed_callback(audio_current_track());
|
|
||||||
update_playlist();
|
update_playlist();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1134,8 +1102,7 @@ static void start_playback_if_ready(void)
|
||||||
if (play_pending_track_change)
|
if (play_pending_track_change)
|
||||||
{
|
{
|
||||||
play_pending_track_change = false;
|
play_pending_track_change = false;
|
||||||
if(track_changed_callback)
|
send_event(PLAYBACK_EVENT_TRACK_CHANGE, false, audio_current_track());
|
||||||
track_changed_callback(audio_current_track());
|
|
||||||
}
|
}
|
||||||
play_pending = false;
|
play_pending = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue