New feature: clean shutdown if you press OFF twice in the file browser, or select "Shut
off" in the main menu. Players only have the menu option, due to lack of keys.


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4940 a1c6a512-1295-4272-9138-f99709370657
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 062c7a0..22fbb57 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -2793,3 +2793,15 @@
 eng: "Super bass"
 voice: "Super bass"
 new:
+
+id: LANG_SHUTDOWN
+desc:  in main menu
+eng: "Shut down"
+voice: "Shut down"
+new:
+
+id: LANG_SHUTTINGDOWN
+desc:  in main menu
+eng: "Shutting down..."
+voice: ""
+new:
diff --git a/apps/main_menu.c b/apps/main_menu.c
index 462d10d..991a168 100644
--- a/apps/main_menu.c
+++ b/apps/main_menu.c
@@ -49,7 +49,7 @@
 #ifdef HAVE_FMRADIO
 #include "radio.h"
 #endif
-
+#include "misc.h"
 #include "lang.h"
 
 #ifdef HAVE_MAS3587F
@@ -324,7 +324,7 @@
     int i = 0;
 
     /* main menu */
-    struct menu_item items[8];
+    struct menu_item items[9];
 
     items[i].desc = ID2P(LANG_BOOKMARK_MENU);
     items[i++].function = bookmark_menu;
@@ -356,6 +356,9 @@
     items[i].desc = ID2P(LANG_INFO);
     items[i++].function = info_menu;
 
+    items[i].desc = ID2P(LANG_SHUTDOWN);
+    items[i++].function = clean_shutdown;
+
     m=menu_init( items, i, NULL, NULL, NULL, NULL );
 #ifdef HAVE_LCD_CHARCELLS
     status_set_param(true);
diff --git a/apps/misc.c b/apps/misc.c
index 535cd81..8bb78f5 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -17,6 +17,7 @@
  *
  ****************************************************************************/
 #include <ctype.h>
+#include "lang.h"
 #include "string.h"
 #include "config.h"
 #include "file.h"
@@ -25,6 +26,13 @@
 #include "errno.h"
 #include "system.h"
 #include "timefuncs.h"
+#include "screens.h"
+#include "mpeg.h"
+#include "mp3_playback.h"
+#include "settings.h"
+#include "ata.h"
+#include "kernel.h"
+#include "power.h"
 
 #define ONE_KILOBYTE 1024
 #define ONE_MEGABYTE (1024*1024)
@@ -204,3 +212,23 @@
     *value = ptr;
     return true;
 }
+
+bool clean_shutdown(void)
+{
+    lcd_clear_display();
+    splash(0, true, str(LANG_SHUTTINGDOWN));
+    mpeg_stop();
+    settings_save();
+    ata_flush();
+    ata_spindown(1);
+#ifndef SIMULATOR
+    while(ata_disk_is_active())
+        sleep(HZ/10);
+    if(!charger_inserted())
+    {
+       mp3_shutdown();
+        power_off();
+    }
+#endif
+    return false;
+}
diff --git a/apps/misc.h b/apps/misc.h
index df9eba8..7815bd2 100644
--- a/apps/misc.h
+++ b/apps/misc.h
@@ -39,5 +39,6 @@
 #endif
 
 bool settings_parseline(char* line, char** name, char** value);
+bool clean_shutdown(void);
 
 #endif
diff --git a/apps/screens.c b/apps/screens.c
index 28d9a48..c099822 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -39,6 +39,7 @@
 #include "adc.h"
 #include "action.h"
 #include "talk.h"
+#include "misc.h"
 
 #ifdef HAVE_LCD_BITMAP
 #define BMPHEIGHT_usb_logo 32
@@ -1090,3 +1091,41 @@
     return false;
 }
 #endif
+
+bool shutdown_screen(void)
+{
+    int button;
+    bool done = false;
+
+    lcd_stop_scroll();
+
+#ifdef HAVE_LCD_CHARCELLS
+    splash(0, true, "Push STOP to shut off");
+#else
+    splash(0, true, "Push OFF to shut off");
+#endif
+    while(!done)
+    {
+        button = button_get_w_tmo(HZ*2);
+        switch(button)
+        {
+#ifdef HAVE_PLAYER_KEYPAD
+            case BUTTON_STOP:
+#else
+            case BUTTON_OFF:
+#endif
+                clean_shutdown();
+                break;
+
+            default:
+                /* Return if any other button was pushed, or if there
+                   was a timeout. We ignore RELEASE events, since we may
+                   have been called by a button down event, and the user might
+                   not have released the button yet. */
+                if(!(button & BUTTON_REL))
+                   done = true;
+                break;
+        }
+    }
+    return false;
+}
diff --git a/apps/screens.h b/apps/screens.h
index 55b3100..b4f293f 100644
--- a/apps/screens.h
+++ b/apps/screens.h
@@ -40,6 +40,8 @@
 #ifdef HAVE_RTC
 bool set_time_screen(char* string, struct tm *tm);
 #endif
-    
+
+bool shutdown_screen(void);
+
 #endif
 
diff --git a/apps/tree.c b/apps/tree.c
index 754e84f..1faadf6 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -1012,18 +1012,18 @@
                 break;
 
 #ifdef HAVE_RECORDER_KEYPAD
-            case BUTTON_OFF:
-                bookmark_autobookmark();
-                mpeg_stop();
-                status_draw(false);
-                restore = true;
-                break;
-
             case BUTTON_OFF | BUTTON_REL:
-#else
-            case BUTTON_STOP | BUTTON_REL:
 #endif
-                settings_save();
+                /* Stop the music if it is playing, else show the shutdown
+                   screen */
+                if(mpeg_status())
+                    mpeg_stop();
+                else {
+                    if (!charger_inserted()) {
+                        shutdown_screen();
+                        restore = true;
+                    }
+                }
                 break;
 
 #ifdef HAVE_RECORDER_KEYPAD
diff --git a/firmware/export/mp3_playback.h b/firmware/export/mp3_playback.h
index b4719b7..9eb1d88 100644
--- a/firmware/export/mp3_playback.h
+++ b/firmware/export/mp3_playback.h
@@ -60,6 +60,7 @@
 void mp3_reset_playtime(void);
 bool mp3_is_playing(void);
 unsigned char* mp3_get_pos(void);
+void mp3_shutdown(void);
 
 
 #define SOUND_VOLUME 0
diff --git a/firmware/mp3_playback.c b/firmware/mp3_playback.c
index 44a7eef..c6f1626 100644
--- a/firmware/mp3_playback.c
+++ b/firmware/mp3_playback.c
@@ -1028,6 +1028,20 @@
     paused = true;
 }
 
+void mp3_shutdown(void)
+{
+#ifndef SIMULATOR
+#ifdef HAVE_MAS3587F
+    unsigned long val = 1;
+    mas_writemem(MAS_BANK_D0, 0x7f9, &val, 1); /* Mute */
+#endif
+
+#ifdef HAVE_MAS3507D
+    dac_volume(0, 0, false);
+#endif
+
+#endif
+}
 
 /* new functions, to be exported to plugin API */