Index: apps/recorder/recording.c
===================================================================
--- apps/recorder/recording.c	(revision 27875)
+++ apps/recorder/recording.c	(working copy)
@@ -1591,6 +1591,14 @@
                 /* Only act if the mpeg is stopped */
                 if(!(audio_stat & AUDIO_STATUS_RECORD))
                 {
+                    /*
+                        If recording kicks off again, check and start the sleep timer
+                    */
+                    if (global_settings.sleeptimer_on_startup == true)
+                    {
+                        set_sleep_timer(global_settings.sleeptimer_duration * 60);
+                    }
+                    
                     /* is this manual or triggered recording? */
                     if ((global_settings.rec_trigger_mode == TRIG_MODE_OFF) ||
                          (peak_meter_trigger_status() != TRIG_OFF))
Index: apps/lang/english.lang
===================================================================
--- apps/lang/english.lang	(revision 27875)
+++ apps/lang/english.lang	(working copy)
@@ -4417,7 +4417,7 @@
 </phrase>
 <phrase>
   id: LANG_SLEEP_TIMER
-  desc: sleep timer setting
+  desc: sleep timer menu
   user: core
   <source>
     *: "Sleep Timer"
@@ -12619,3 +12619,59 @@
     *: "Update on Stop"
   </voice>
 </phrase>
+<phrase>
+  id: LANG_SLEEP_TIMER_START
+  desc: start sleep timer
+  user: core
+  <source>
+    *: "Start Timer"
+  </source>
+  <dest>
+    *: "Start Timer"
+  </dest>
+  <voice>
+    *: "Start Timer"
+  </voice>
+</phrase>
+<phrase>
+  id: LANG_SLEEP_TIMER_STOP
+  desc: stop sleep timer
+  user: core
+  <source>
+    *: "Stop Timer"
+  </source>
+  <dest>
+    *: "Stop Timer"
+  </dest>
+  <voice>
+    *: "Stop Timer"
+  </voice>
+</phrase>
+<phrase>
+  id: LANG_SLEEP_TIMER_DURATION
+  desc: sleep timer duration in minutes
+  user: core
+  <source>
+    *: "Timer Duration"
+  </source>
+  <dest>
+    *: "Timer Duration"
+  </dest>
+  <voice>
+    *: "Timer Duration"
+  </voice>
+</phrase>
+<phrase>
+  id: LANG_SLEEP_TIMER_ON_POWER_UP
+  desc: whether sleep timer starts on power up
+  user: core
+  <source>
+    *: "Start Timer On Power Up?"
+  </source>
+  <dest>
+    *: "Start Timer On Power Up?"
+  </dest>
+  <voice>
+    *: "Start Timer On Power Up?"
+  </voice>
+</phrase>
Index: apps/gui/wps.c
===================================================================
--- apps/gui/wps.c	(revision 27875)
+++ apps/gui/wps.c	(working copy)
@@ -691,6 +691,7 @@
  * In either way, call gwps_leave_wps(), in order to restore the correct
  * "main screen" backdrops and statusbars
  */
+extern void set_sleep_timer(int seconds);
 long gui_wps_show(void)
 {
     long button = 0;
@@ -814,6 +815,12 @@
                         fade(true, true);
                     else
                         audio_resume();
+                   /* restart sleep timer if it is currently enabled for startup */
+                    if (global_settings.sleeptimer_on_startup == true)
+                    {
+                        set_sleep_timer(global_settings.sleeptimer_duration * 60);
+                    }
+
                 }
                 else
                 {
@@ -822,6 +829,9 @@
                         fade(false, true);
                     else
                         audio_pause();
+                    /* stopping sleep timer at any pause - sleeptimer_on_startup can be ignored here */
+                    set_sleep_timer(0);
+                        
                     settings_save();
 #if !defined(HAVE_RTC_RAM) && !defined(HAVE_SW_POWEROFF)
                     call_storage_idle_notifys(true);   /* make sure resume info is saved */
Index: apps/settings.h
===================================================================
--- apps/settings.h	(revision 27875)
+++ apps/settings.h	(working copy)
@@ -772,6 +772,9 @@
     int compressor_release_time;
 #endif
 
+    int sleeptimer_duration;
+    bool sleeptimer_on_startup;
+
 #ifdef HAVE_MORSE_INPUT
     bool morse_input; /* text input method setting */
 #endif
Index: apps/menus/exported_menus.h
===================================================================
--- apps/menus/exported_menus.h	(revision 27875)
+++ apps/menus/exported_menus.h	(working copy)
@@ -44,7 +44,8 @@
         audiohw_eq_tone_controls,   /* audiohw_eq_menu.c */
 #endif
         info_menu,                  /* info_menu.c      */
-        theme_menu;                 /* theme_menu.c     */
+        theme_menu,                 /* theme_menu.c     */
+        sleeptimer_menu;            /* sleeptimer_menu.c */
 
 struct browse_folder_info {
     const char* dir;
Index: apps/menus/main_menu.c
===================================================================
--- apps/menus/main_menu.c	(revision 27875)
+++ apps/menus/main_menu.c	(working copy)
@@ -384,46 +384,11 @@
 MENUITEM_FUNCTION(show_info_item, 0, ID2P(LANG_ROCKBOX_INFO),
                    (menu_function)show_info, NULL, NULL, Icon_NOICON);
 
-
-/* sleep Menu */
-static const char* sleep_timer_formatter(char* buffer, size_t buffer_size,
-                                         int value, const char* unit)
-{
-    (void) unit;
-    int minutes, hours;
-
-    if (value) {
-        hours = value / 60;
-        minutes = value - (hours * 60);
-        snprintf(buffer, buffer_size, "%d:%02d", hours, minutes);
-        return buffer;
-    } else {
-        return str(LANG_OFF);
-    }
-}
-
-static void sleep_timer_set(int minutes)
-{
-    set_sleep_timer(minutes * 60);
-}
-
-static int sleep_timer(void)
-{
-    int minutes = (get_sleep_timer() + 59) / 60; /* round up */
-    return (int)set_int(str(LANG_SLEEP_TIMER), "", UNIT_MIN, &minutes,
-                   &sleep_timer_set, -5, 300, 0, sleep_timer_formatter);
-}
-
-
 #if CONFIG_RTC
 int time_screen(void* ignored);
 MENUITEM_FUNCTION(timedate_item, MENU_FUNC_CHECK_RETVAL, ID2P(LANG_TIME_MENU),
                     time_screen, NULL,  NULL, Icon_Menu_setting );
 #endif
-/* This item is in the time/date screen if there is a RTC */
-MENUITEM_FUNCTION(sleep_timer_call, 0, ID2P(LANG_SLEEP_TIMER), sleep_timer,
-                    NULL, NULL, Icon_Menu_setting); /* make it look like a 
-                                                       setting to the user */
 
 MENUITEM_FUNCTION(show_credits_item, 0, ID2P(LANG_CREDITS),
                    (menu_function)show_credits, NULL, NULL, Icon_NOICON);
@@ -436,11 +401,8 @@
 #if CONFIG_RTC
           &timedate_item,
 #endif
-          &show_info_item, &show_credits_item, &show_runtime_item, 
-#if CONFIG_RTC == 0
-          &sleep_timer_call, 
-#endif
-          &debug_menu_item);
+          &sleeptimer_menu, &show_info_item, &show_credits_item,
+          &show_runtime_item, &debug_menu_item);
 /*      INFO MENU                  */
 /***********************************/
 
Index: apps/menus/time_menu.c
===================================================================
--- apps/menus/time_menu.c	(revision 27875)
+++ apps/menus/time_menu.c	(working copy)
@@ -81,8 +81,6 @@
                   timedate_set, NULL, NULL, Icon_NOICON);
 MENUITEM_SETTING(timeformat, &global_settings.timeformat, NULL);
 
-/* in main_menu.c */
-extern const struct menu_item_ex sleep_timer_call;
 
 #ifdef HAVE_RTC_ALARM
 MENUITEM_FUNCTION(alarm_screen_call, 0, ID2P(LANG_ALARM_MOD_ALARM_MENU),
@@ -239,7 +237,7 @@
 
 
 MAKE_MENU(time_menu, ID2P(LANG_TIME_MENU), time_menu_callback, Icon_NOICON,
-          &time_set, &sleep_timer_call,
+          &time_set,
 #ifdef HAVE_RTC_ALARM
           &alarm_screen_call,
 #if defined(HAVE_RECORDING) || CONFIG_TUNER
Index: apps/settings_list.c
===================================================================
--- apps/settings_list.c	(revision 27875)
+++ apps/settings_list.c	(working copy)
@@ -520,6 +520,14 @@
     return get_hotkey_lang_id(value);
 }
 #endif /* HAVE_HOTKEY */
+static const char* sleeptimer_formatter(char* buffer, size_t buffer_size,
+                                         int value, const char* unit)
+{
+    (void) unit;
+    snprintf(buffer, buffer_size, "%d:%02d",
+                value / 60, value % 60);
+    return buffer;
+}
 const struct settings_list settings[] = {
     /* sound settings */
     SOUND_SETTING(F_NO_WRAP,volume, LANG_VOLUME, "volume", SOUND_VOLUME),
@@ -1672,6 +1680,9 @@
 #endif /* CONFIG_CODEC == SWCODEC */
     TEXT_SETTING(0, playlist_catalog_dir, "playlist catalog directory",
                      PLAYLIST_CATALOG_DEFAULT_DIR, NULL, NULL),
+    INT_SETTING(0, sleeptimer_duration, LANG_SLEEP_TIMER_DURATION, 30, "sleeptimer duration",
+                    UNIT_MIN, 300, 5, -5, sleeptimer_formatter, NULL, NULL),
+    OFFON_SETTING(0, sleeptimer_on_startup, LANG_SLEEP_TIMER_ON_POWER_UP, false, "sleeptimer on startup", NULL),
 #ifdef HAVE_TOUCHPAD_SENSITIVITY_SETTING
     CHOICE_SETTING(0, touchpad_sensitivity, LANG_TOUCHPAD_SENSITIVITY, 0,
                    "touchpad sensitivity", "normal,high", touchpad_set_sensitivity, 2,
Index: apps/SOURCES
===================================================================
--- apps/SOURCES	(revision 27875)
+++ apps/SOURCES	(working copy)
@@ -37,6 +37,7 @@
 #if CONFIG_RTC
 menus/time_menu.c
 #endif
+menus/sleeptimer_menu.c
 misc.c
 mp3data.c
 onplay.c
Index: apps/root_menu.c
===================================================================
--- apps/root_menu.c	(revision 27875)
+++ apps/root_menu.c	(working copy)
@@ -608,6 +608,11 @@
         (global_settings.unplug_autoresume && !headphones_inserted() ))
             next_screen = GO_TO_ROOT;
 #endif
+    /*
+     * Restore sleeptimer if required
+     */ 
+    if (global_settings.sleeptimer_on_startup)
+        set_sleep_timer(global_settings.sleeptimer_duration * 60);
 
     while (true)
     {
Index: apps/main.c
===================================================================
--- apps/main.c	(revision 27875)
+++ apps/main.c	(working copy)
@@ -353,6 +353,7 @@
     sim_tasks_init();
     lang_init(core_language_builtin, language_strings, 
               LANG_LAST_INDEX_IN_ARRAY);
+    powermgmt_init();
 #ifdef DEBUG
     debug_init();
 #endif
Index: firmware/export/powermgmt.h
===================================================================
--- firmware/export/powermgmt.h	(revision 27875)
+++ firmware/export/powermgmt.h	(working copy)
@@ -126,10 +126,11 @@
 extern const unsigned short percent_to_volt_charge[11];
 #endif
 
+#endif /* PLATFORM_NATIVE */
+
 /* Start up power management thread */
 void powermgmt_init(void) INIT_ATTR;
 
-#endif /* PLATFORM_NATIVE */
 
 /* Returns battery statust */
 int battery_level(void); /* percent */
Index: firmware/target/hosted/sdl/system-sdl.c
===================================================================
--- firmware/target/hosted/sdl/system-sdl.c	(revision 27875)
+++ firmware/target/hosted/sdl/system-sdl.c	(working copy)
@@ -65,10 +65,9 @@
 int wps_verbose_level = 3;
 
 
-void sys_poweroff(void)
-{
-}
+extern void sys_poweroff(void);
 
+
 /*
  * This thread will read the buttons in an interrupt like fashion, and
  * also initializes SDL_INIT_VIDEO and the surfaces
Index: firmware/powermgmt.c
===================================================================
--- firmware/powermgmt.c	(revision 27875)
+++ firmware/powermgmt.c	(working copy)
@@ -354,7 +354,19 @@
     else if (sleeptimer_active) {
         /* Handle sleeptimer */
         if (TIME_AFTER(tick, sleeptimer_endtick)) {
-            audio_stop();
+            if ((audio_stat & AUDIO_STATUS_RECORD) || (audio_stat & AUDIO_STATUS_PRERECORD)) {
+                audio_pause_recording();
+            }
+                
+            if (get_radio_status() & FMRADIO_PLAYING) {
+                radio_pause();
+            }
+            
+            if (audio_stat & AUDIO_STATUS_PLAY) {
+                audio_pause();
+            }
+            
+            sleeptimer_active = false;
 
             if (usb_inserted()
 #if CONFIG_CHARGING && !defined(HAVE_POWEROFF_WHILE_CHARGING)
@@ -365,10 +377,6 @@
                 set_sleep_timer(0);
                 backlight_off(); /* Nighty, nighty... */
             }
-            else {
-                DEBUGF("Sleep timer timeout. Shutting off...\n");
-                sys_poweroff();
-            }
         }
     }
 }
Index: uisimulator/common/stubs.c
===================================================================
--- uisimulator/common/stubs.c	(revision 27875)
+++ uisimulator/common/stubs.c	(working copy)
@@ -32,6 +32,7 @@
 #include "power.h"
 
 #include "ata.h" /* for volume definitions */
+#include "kernel.h" /* access to current_tick */
 
 static bool storage_spinning = false;
 
@@ -279,17 +280,6 @@
     (void)pitch;
 }
 
-static int sleeptime;
-void set_sleep_timer(int seconds)
-{
-    sleeptime = seconds;
-}
-
-int get_sleep_timer(void)
-{
-    return sleeptime;
-}
-
 #ifdef HAVE_LCD_CHARCELLS
 void lcd_clearrect (int x, int y, int nx, int ny)
 {
Index: uisimulator/common/powermgmt-sim.c
===================================================================
--- uisimulator/common/powermgmt-sim.c	(revision 27875)
+++ uisimulator/common/powermgmt-sim.c	(working copy)
@@ -23,13 +23,39 @@
 #include "system.h"
 #include <time.h>
 #include "kernel.h"
+#include "power.h"
 #include "powermgmt.h"
+#include "debug.h"
+#include "string.h"
+#include "audio.h"
+#include "thread-sdl.h"
+#include "SDL.h"
 
 #define BATT_MINMVOLT   2500      /* minimum millivolts of battery */
 #define BATT_MAXMVOLT   4500      /* maximum millivolts of battery */
 #define BATT_MAXRUNTIME (10 * 60) /* maximum runtime with full battery in
                                      minutes */
+static bool sleeptimer_active = false;
+static long sleeptimer_endtick;
+static long last_event_tick;
+static int poweroff_timeout = 0;
+ 
 
+/* Power history: power_history[0] is the newest sample */
+unsigned short power_history[POWER_HISTORY_LEN];
+
+#define POWERMGMT_DEBUG_STACK 0
+
+/* 2HZ sample rate unless otherwise specified */
+#define POWER_THREAD_STEP_TICKS (HZ/2)
+
+#if CONFIG_CPU == JZ4732 /* FIXME! */
+static char power_stack[DEFAULT_STACK_SIZE + POWERMGMT_DEBUG_STACK];
+#else
+static char power_stack[DEFAULT_STACK_SIZE/2 + POWERMGMT_DEBUG_STACK];
+#endif
+static const char power_thread_name[] = "power";
+
 extern void send_battery_level_event(void);
 extern int last_sent_battery_level;
 extern int battery_percent;
@@ -120,7 +146,7 @@
 
 void set_poweroff_timeout(int timeout)
 {
-    (void)timeout;
+    poweroff_timeout = timeout;
 }
 
 void set_battery_capacity(int capacity)
@@ -128,6 +154,107 @@
   (void)capacity;
 }
 
+
+
+/*
+ * We shut off in the following cases:
+ * 1) The unit is idle, not playing music
+ * 2) The unit is playing music, but is paused
+ * 3) The battery level has reached shutdown limit
+ *
+ * We do not shut off in the following cases:
+ * 1) The USB is connected
+ * 2) The charger is connected
+ * 3) We are recording, or recording with pause
+ * 4) The radio is playing
+ */
+static void handle_auto_poweroff(void)
+{
+    DEBUGF("handle_auto_poweroff()\n");
+    long timeout = poweroff_timeout*60*HZ;
+    int audio_stat = audio_status();
+    long tick = current_tick;
+
+    if (timeout &&
+        (audio_stat == 0 ||
+         (audio_stat == (AUDIO_STATUS_PLAY | AUDIO_STATUS_PAUSE) &&
+          !sleeptimer_active))) {
+
+        if (TIME_AFTER(tick, last_event_tick + timeout)) {
+            sys_poweroff();
+        }
+    }
+    else if (sleeptimer_active) {
+        /* Handle sleeptimer */
+        if (TIME_AFTER(tick, sleeptimer_endtick)) {
+            DEBUGF("Sleep timer timeout. Pause Playing...\n");
+            audio_pause();
+            sleeptimer_active = false;
+        }
+    }
+}
+
+
+static void power_thread(void)
+{
+    DEBUGF("power_thread() starting\n");
+    long next_power_hist;
+
+    next_power_hist = current_tick + HZ*60;
+
+    while (1)
+    {
+
+       /* Steady state */
+        sleep(POWER_THREAD_STEP_TICKS);
+
+        if (TIME_BEFORE(current_tick, next_power_hist))
+            continue;
+
+        /* increment to ensure there is a record for every minute
+         * rather than go forward from the current tick */
+        next_power_hist += HZ*60;
+       
+        handle_auto_poweroff();
+    }
+} /* power_thread */
+
+
+void powermgmt_init(void)
+{
+    /* init history to 0 */
+    create_thread(power_thread, power_stack, sizeof(power_stack), 0,
+                  power_thread_name IF_PRIO(, PRIORITY_SYSTEM)
+                  IF_COP(, CPU));
+}
+
+void set_sleep_timer(int seconds)
+{
+    if (seconds) {
+        DEBUGF("Setting sleep timer to %d seconds (%d minutes)\n", seconds, seconds/60);
+        sleeptimer_active  = true;
+        sleeptimer_endtick = current_tick + seconds * HZ;
+    } else {
+        DEBUGF("Disabling sleep timer\n");
+        sleeptimer_active  = false;
+        sleeptimer_endtick = 0;
+    }
+}
+
+int get_sleep_timer(void)
+{
+   if (sleeptimer_active) {
+        if (TIME_AFTER(sleeptimer_endtick, current_tick))
+            return (sleeptimer_endtick - current_tick) / HZ;
+        DEBUGF("Sleep timer finished\n");
+        set_sleep_timer(0);
+    }
+    return 0;
+}
+
+
+
+
 #if BATTERY_TYPES_COUNT > 1
 void set_battery_type(int type)
 {
@@ -151,12 +278,30 @@
 
 void reset_poweroff_timer(void)
 {
+    last_event_tick = current_tick;
 }
 
 void shutdown_hw(void)
 {
 }
 
+ void sys_poweroff(void)
+ {
+    power_off();
+ }
+
+extern int playlist_update_resume_info(const struct mp3entry* id3);
+void power_off(void)
+{
+    /* just to be sure the offset is actual */
+    playlist_update_resume_info(audio_current_track());
+    
+    SDL_Event event;
+    event.type = SDL_QUIT;
+    SDL_PushEvent (&event);
+}
+
+
 void cancel_shutdown(void)
 {
 }
Index: manual/appendix/config_file_options.tex
===================================================================
--- manual/appendix/config_file_options.tex	(revision 27875)
+++ manual/appendix/config_file_options.tex	(working copy)
@@ -365,6 +365,10 @@
       jump scroll delay
                 & 0 to 250              & 0.01~s\\
     }%
+    sleeptimer duration   & 5 to 300 (in steps of 5)
+                                        & minutes\\
+    sleeptimer on startup & off, on     & N/A\\
+ 
 
     \bottomrule
   \end{longtable}
Index: manual/main_menu/main.tex
===================================================================
--- manual/main_menu/main.tex	(revision 27875)
+++ manual/main_menu/main.tex	(working copy)
@@ -200,11 +200,6 @@
     Time related menu options. Pressing \ActionStdContext{} will voice the current time if voice support is enabled
     \begin{description}
       \item [Set Time/Date: ] Set current time and date.
-      \item[Sleep Timer:]
-        The \setting{Sleep Timer} powers off your \dap{} after playing for a given
-        time. It can be set from \setting{Off} to 5 hours in 5 minute steps.
-        The \setting{Sleep Timer} is reset on boot.
-        \opt{alarm}{Using this option disables the \setting{Wake up alarm}.}
       \item [Time Format: ] Choose 12 or 24 hour clock.
       \opt{alarm}{
         \subsection{Wake-Up Alarm}
@@ -222,6 +217,26 @@
       }
     \end{description}
 }
+
+\item[Sleep Timer:]
+  Sleep Timer related menu options.
+  The \setting{Sleep Timer} pauses your \dap{} after a given time.
+  \opt{alarm}{The \setting{Wake up alarm} is disabled while the timer is active.}
+  \begin{description}
+    \item[Start Timer (\emph{duration}):]
+      Shown when the timer is inactive, this option will initiate the timer with the duration shown in brackets.
+    \item[Stop Timer (\emph{remaining}):]
+      Shown when the timer is active, this option will disable the current timer.
+      The time remaining before completion is shown in brackets.
+    \item[Timer Duration:]
+      The number of minutes from when new timers are initiated to their completion.
+      The values range from 5 minutes to 5 hours in 5 minute steps.
+      If a timer is currently active, the timer's duration will be set to the newly entered value.
+      The value set is persistent, see \reference{ref:config_file_options}.
+    \item[Start Timer On Power Up?:]
+      If set, a timer will be initiated when the device starts.
+      The value set is persistent.
+  \end{description}
 \item[Rockbox Info:]
   Displays some basic system information. This is, from top to bottom,
   the amount of memory Rockbox has available for storing music (the buffer).
@@ -238,14 +253,6 @@
 \item[Credits:]
   Display the list of contributors.
 
-\nopt{rtc}{
-  \item[Sleep Timer:]
-    The \setting{Sleep Timer} powers off your \dap{} after playing for a given
-    time. It can be set from \setting{Off} to 5 hours in 5 minute steps.
-    The \setting{Sleep Timer} is reset on boot.
-    \opt{alarm}{Using this option disables the \setting{Wake up alarm}.}
-}
-
 \item[Debug (Keep Out!):]
   This sub menu is intended to be used \emph{only} by Rockbox developers.
   It shows hardware, disk, battery status and other technical information.  
