Index: apps/settings.c
===================================================================
--- apps/settings.c	(revision 13558)
+++ apps/settings.c	(working copy)
@@ -515,13 +515,15 @@
     return true;
 }
 #ifndef HAVE_RTC_RAM
-static bool flush_global_status_callback(void)
+static bool flush_global_status_callback(void* data)
 {
+    (void)data;
     return write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
 }
 #endif
-static bool flush_config_block_callback(void)
+static bool flush_config_block_callback(void* data)
 {
+    (void)data;
     bool r1, r2;
     r1 = write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
     r2 = settings_write_config(CONFIGFILE, SETTINGS_SAVE_CHANGED);
Index: apps/playback.c
===================================================================
--- apps/playback.c	(revision 13558)
+++ apps/playback.c	(working copy)
@@ -3538,8 +3538,9 @@
 #if MEM > 8
 /* we dont want this rebuffering on targets with little ram
    because the disk may never spin down */
-static bool ata_fillbuffer_callback(void)
+static bool ata_fillbuffer_callback(void* data)
 {
+    (void)data;
     queue_post(&audio_queue, Q_AUDIO_FILL_BUFFER_IF_ACTIVE_ATA, 0);
     return true;
 }
Index: apps/scrobbler.c
===================================================================
--- apps/scrobbler.c	(revision 13558)
+++ apps/scrobbler.c	(working copy)
@@ -132,8 +132,9 @@
     scrobbler_fd = -1;
 }
 
-static bool scrobbler_flush_callback(void)
+static bool scrobbler_flush_callback(void* data)
 {
+    (void)data;
     if (scrobbler_initialised && cache_pos)
         write_cache();
     return true;
Index: apps/main.c
===================================================================
--- apps/main.c	(revision 13558)
+++ apps/main.c	(working copy)
@@ -19,7 +19,7 @@
 #include "config.h"
 
 #include "ata.h"
-#include "ata_idle_notify.h"
+#include "event_callback.h"
 #include "disk.h"
 #include "fat.h"
 #include "lcd.h"
@@ -259,6 +259,7 @@
 #ifdef DEBUG
     debug_init();
 #endif
+    event_callback_init();
     /* Must be done before any code uses the multi-screen APi */
     screen_access_init();
     gui_syncstatusbar_init(&statusbars);
@@ -399,7 +400,7 @@
     }
 #endif
 
-    ata_idle_notify_init();
+    event_callback_init();
     rc = ata_init();
     if(rc)
     {
Index: firmware/export/ata_idle_notify.h
===================================================================
--- firmware/export/ata_idle_notify.h	(revision 13558)
+++ firmware/export/ata_idle_notify.h	(working copy)
@@ -20,6 +20,7 @@
 #define __ATACALLBACK_H__
 
 #include <stdbool.h>
+#include "event_callback.h"
 
 #if 0
                 NOTE: ata_idle_nofity usage notes..
@@ -34,21 +35,22 @@
         5) Dont Panic!
 #endif
 
-#define USING_ATA_CALLBACK  !defined(SIMULATOR)             \
-                            && !defined(HAVE_FLASH_DISK)
+#if !defined(SIMULATOR) && !defined(HAVE_FLASH_DISK)
 
-#define MAX_ATA_CALLBACKS 5
-typedef bool (*ata_idle_notify)(void);
-
-extern bool register_ata_idle_func(ata_idle_notify function);
-#if USING_ATA_CALLBACK
-extern void ata_idle_notify_init(void);
-extern void unregister_ata_idle_func(ata_idle_notify function, bool run);
-extern bool call_ata_idle_notifys(bool force);
+#define register_ata_idle_func(f)       \
+        register_event_callback(EID_ATA_DISK_SPINUP, (event_callback)f)
+        
+#define unregister_ata_idle_func(f,r)   \
+        unregister_event_callback(EID_ATA_DISK_SPINUP, (event_callback)f, r)
+        
+#define call_ata_idle_notifys(f)        \
+        call_event_callbacks(EID_ATA_DISK_SPINUP, (event_callback)f)
+        
 #else
+#define register_ata_idle_func(f) (f(NULL)?true:true) /* always pretend \
+                                                        it was registered */
 #define unregister_ata_idle_func(f,r)
 #define call_ata_idle_notifys(f)
-#define ata_idle_notify_init(s)
 #endif
 
 #endif /* __ATACALLBACK_H__ */
Index: firmware/export/event_callback.h
===================================================================
--- firmware/export/event_callback.h	(revision 0)
+++ firmware/export/event_callback.h	(revision 0)
@@ -0,0 +1,57 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id: ata_idle_notify.h 11599 2006-11-26 09:53:42Z jdgordon $
+ *
+ * Copyright (C) 2006 Jonathan Gordon
+ *
+ * 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 __EVENTCALLBACKS_H__
+#define __EVENTCALLBACKS_H__
+
+#include <stdbool.h>
+
+#if 0
+                NOTE: Usage notes..
+                
+        1) Do not call cany yielding functions in the callback
+        2) Do not call ata_sleep in the callbacks
+#endif
+
+typedef bool (*event_callback)(void* data);
+
+enum event_id {
+    EID_ATA_DISK_SPINUP, /* called from ata thread, data == NULL */
+    EID_PLAYBACK_STARTED, /* playback thread, data = ? */
+    EID_PLAYBACK_STOPPED, /* playback thread, data = ? */
+    EID_TRACK_CHANGED, /* playback thread, data = ? */
+    EID_TRACK_BUFFERED, /* playback thread, data = ? */
+    EID_TRACK_UNBUFFERED, /* playback thread, data = ? */
+};
+
+/* event - EID_ number this callback is called for
+   funtion - funtion to call
+   */
+extern bool register_event_callback(enum event_id event, 
+                                    event_callback function);
+/* run - call the callback before removing 
+        it from the list, data will always be NULL */
+extern void unregister_event_callback(enum event_id event, 
+                                event_callback function, bool run);
+/* call all the registered events for a event_id */
+extern bool call_event_callbacks(enum event_id event, void* data);
+
+
+extern void event_callback_init(void); /* call from main() */
+
+#endif /* __EVENTCALLBACKS_H__ */
Index: firmware/SOURCES
===================================================================
--- firmware/SOURCES	(revision 13558)
+++ firmware/SOURCES	(working copy)
@@ -1,6 +1,6 @@
-ata_idle_notify.c
 backlight.c
 buffer.c
+event_callback.c
 id3.c
 powermgmt.c
 system.c
Index: firmware/ata_idle_notify.c
===================================================================
--- firmware/ata_idle_notify.c	(revision 13558)
+++ firmware/ata_idle_notify.c	(working copy)
@@ -1,105 +0,0 @@
-/***************************************************************************
- *             __________               __   ___.
- *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
- *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
- *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
- *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
- *                     \/            \/     \/    \/            \/
- * $Id$
- *
- * Copyright (C) 2006 Jonathan Gordon
- *
- * 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 <stdbool.h>
-#include "system.h"
-#include "ata.h"
-#include "ata_idle_notify.h"
-#include "kernel.h"
-#include "string.h"
-
-#if USING_ATA_CALLBACK
-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
-    int i;
-    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
-    function(); /* just call the function now */
-/* this _may_ cause problems later if the calling function
-   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 */
-    return true;
-#endif
-}
-
-#if USING_ATA_CALLBACK
-void unregister_ata_idle_func(ata_idle_notify func, bool run)
-{
-    int i;
-    for (i=0; i<MAX_ATA_CALLBACKS; i++)
-    {
-        if (ata_idle_notify_funcs[i] == func)
-        {
-            ata_idle_notify_funcs[i] = NULL;
-            ata_callback_count--;
-            if (run) func();
-        }
-    }
-    return;
-}
-
-bool call_ata_idle_notifys(bool force)
-{
-    int i;
-    static int lock_until = 0;
-    ata_idle_notify function;
-    if (!force)
-    {
-        if (TIME_BEFORE(current_tick,lock_until) )
-            return false;
-    }
-    lock_until = current_tick + 30*HZ;
-
-    for (i = 0; i < MAX_ATA_CALLBACKS; i++)
-    {
-        if (ata_idle_notify_funcs[i])
-        {
-            function = ata_idle_notify_funcs[i];
-            ata_idle_notify_funcs[i] = NULL;
-            function();
-            ata_callback_count--;
-        }
-    }
-    return true;
-}
-
-void ata_idle_notify_init(void)
-{
-    ata_callback_count = 0;
-    memset(ata_idle_notify_funcs, 0, sizeof(ata_idle_notify_funcs));
-}
-#endif
Index: firmware/event_callback.c
===================================================================
--- firmware/event_callback.c	(revision 0)
+++ firmware/event_callback.c	(revision 0)
@@ -0,0 +1,94 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id: ata_idle_notify.c 11674 2006-12-06 12:11:57Z jdgordon $
+ *
+ * Copyright (C) 2006 Jonathan Gordon
+ *
+ * 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 <stdbool.h>
+#include "system.h"
+#include "ata.h"
+#include "event_callback.h"
+#include "kernel.h"
+#include "string.h"
+
+struct callback_info {
+    event_callback function;
+    enum event_id event;
+};
+#define MAX_CALLBACKS 16
+static struct callback_info callbacks[MAX_CALLBACKS];
+static int callback_count = 0;
+
+bool register_event_callback(enum event_id event, 
+                             event_callback function)
+{
+    int i;
+    if (callback_count >= MAX_CALLBACKS)
+        /* possibly panic() here */
+        return false;
+    
+    for (i=0; i<MAX_CALLBACKS; i++)
+    {
+        if (callbacks[i].function == NULL)
+        {
+            callbacks[i].function = function;
+            callbacks[i].event = event;
+            callback_count++;
+            return true;
+        }
+        else if ((callbacks[i].function == function) &&
+                  (callbacks[i].event == event))
+            return true;
+    }
+    return false;
+}
+
+void unregister_event_callback(enum event_id event, 
+                               event_callback function, bool run)
+{
+    int i;
+    for (i=0; i<MAX_CALLBACKS; i++)
+    {
+        if ((callbacks[i].function == function) &&
+             (callbacks[i].event == event))
+        {
+            if (run)
+                callbacks[i].function(NULL);
+            callbacks[i].function = NULL;
+            callback_count--;
+            break;
+        }
+    }
+    return;
+}
+bool call_event_callbacks(enum event_id event, void* data)
+{
+    int i;
+    for (i=0; i<MAX_CALLBACKS; i++)
+    {
+        if ((callbacks[i].function) &&
+             (callbacks[i].event == event))
+        {
+            callbacks[i].function(data);
+        }
+    }
+    return true;
+}
+
+void event_callback_init(void)
+{
+    callback_count = 0;
+    memset(callbacks, 0, sizeof(callbacks));
+}
