1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
diff --git a/apps/gui/wps.c b/apps/gui/wps.c
index d62507e..0af6b8d 100644
--- a/apps/gui/wps.c
+++ b/apps/gui/wps.c
@@ -83,6 +83,7 @@ static struct wps_data wps_datas[NB_SCREENS];
 static void wps_state_init(void);
 static void track_changed_callback(void *param);
 static void nextid3available_callback(void* param);
+static void wps_part_update_cb(void);



@@ -104,66 +105,15 @@ void wps_data_init(enum screen_type screen)
 }

 bool wps_fading_out = false;
-void fade(bool fade_in, bool updatewps)
-{
-    int fp_global_vol = global_settings.volume << 8;
-    int fp_min_vol = sound_min(SOUND_VOLUME) << 8;
-    int fp_step = (fp_global_vol - fp_min_vol) / 30;
-    int i;
-    wps_fading_out = !fade_in;
-    if (fade_in) {
-        /* fade in */
-        int fp_volume = fp_min_vol;

-        /* zero out the sound */
-        sound_set_volume(fp_min_vol >> 8);
-
-        sleep(HZ/10); /* let audio thread run */
-        audio_resume();
-        
-        while (fp_volume < fp_global_vol - fp_step) {
-            fp_volume += fp_step;
-            sound_set_volume(fp_volume >> 8);
-            if (updatewps)
-            {
-                FOR_NB_SCREENS(i)
-                    skin_update(&gui_wps[i], WPS_REFRESH_NON_STATIC);
-            }
-            sleep(1);
-        }
-        sound_set_volume(global_settings.volume);
-    }
-    else {
-        /* fade out */
-        int fp_volume = fp_global_vol;
-
-        while (fp_volume > fp_min_vol + fp_step) {
-            fp_volume -= fp_step;
-            sound_set_volume(fp_volume >> 8);
-            if (updatewps)
-            {
-                FOR_NB_SCREENS(i)
-                    skin_update(&gui_wps[i], WPS_REFRESH_NON_STATIC);
-            }
-            sleep(1);
-        }
-        audio_pause();
-        wps_fading_out = false;
-#if CONFIG_CODEC != SWCODEC
-#ifndef SIMULATOR
-        /* let audio thread run and wait for the mas to run out of data */
-        while (!mp3_pause_done())
-#endif
-            sleep(HZ/10);
-#endif
-
-        /* reset volume to what it was before the fade */
-        sound_set_volume(global_settings.volume);
-    }
+void wps_fade(bool fade_in, bool updatewps)
+{
+    playback_fade_on_pause(fade_in, updatewps ? wps_part_update_cb : NULL);
 }
+
 bool is_wps_fading(void)
 {
-    return wps_fading_out;
+    return (audio_status() & AUDIO_STATUS_PAUSE);
 }

 bool update_onvol_change(struct gui_wps * gwps)
@@ -517,6 +467,13 @@ static void wps_lcd_activation_hook(void)
 }
 #endif

+static void wps_part_update_cb(void)
+{
+    /* post to get an update */
+    if (queue_empty(&button_queue))
+        queue_post(&button_queue, BUTTON_NONE, 0);
+}
+
 static void gwps_leave_wps(void)
 {
     int i, oldbars = VP_SB_HIDE_ALL;
@@ -743,7 +700,7 @@ long gui_wps_show(void)
                 {
                     wps_state.paused = false;
                     if ( global_settings.fade_on_stop )
-                        fade(true, true);
+                        wps_fade(true, true);
                     else
                         audio_resume();
                 }
@@ -751,7 +708,7 @@ long gui_wps_show(void)
                 {
                     wps_state.paused = true;
                     if ( global_settings.fade_on_stop )
-                        fade(false, true);
+                        wps_fade(false, true);
                     else
                         audio_pause();
                     settings_save();
@@ -1093,7 +1050,7 @@ long gui_wps_show(void)
             status_set_audio(false);
 #endif
             if (global_settings.fade_on_stop)
-                fade(false, true);
+                wps_fade(false, true);

             if (bookmark)
                 bookmark_autobookmark();
diff --git a/apps/misc.c b/apps/misc.c
index b091cc6..4e6e3fb 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -332,7 +332,7 @@ static bool clean_shutdown(void (*callback)(void *), void *parameter)
         if (global_settings.fade_on_stop
             && (audio_stat & AUDIO_STATUS_PLAY))
         {
-            fade(false, false);
+            playback_fade_on_pause(false, NULL);
         }

         if (batt_safe) /* do not save on critical battery */
@@ -409,7 +409,7 @@ bool list_stop_handler(void)
         if (!global_settings.party_mode) 
         {
             if (global_settings.fade_on_stop)
-                fade(false, false);
+                playback_fade_on_pause(false, NULL);
             bookmark_autobookmark();
             audio_stop();
             ret = true;  /* bookmarking can make a refresh necessary */
@@ -475,7 +475,7 @@ static void car_adapter_mode_processing(bool inserted)
                 !(audio_status() & AUDIO_STATUS_PAUSE))
             {
                 if (global_settings.fade_on_stop)
-                    fade(false, false);
+                    playback_fade_on_pause(false, NULL);
                 else
                     audio_pause();
             }
diff --git a/apps/playback.c b/apps/playback.c
index 16f4766..2af088c 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -710,6 +710,59 @@ void audio_stop(void)
     queue_send(&audio_queue, Q_AUDIO_STOP, 0);
 }

+void playback_fade_on_pause(bool fade_in, void (*update_func)(void))
+{
+    int fp_global_vol = global_settings.volume << 8;
+    int fp_min_vol = sound_min(SOUND_VOLUME) << 8;
+    int fp_step = (fp_global_vol - fp_min_vol) / 30;
+    if (fade_in) {
+        /* fade in */
+        int fp_volume = fp_min_vol;
+
+        /* zero out the sound */
+        sound_set_volume(fp_min_vol >> 8);
+
+        sleep(HZ/10); /* let audio thread run */
+        audio_resume();
+        
+        while (fp_volume < fp_global_vol - fp_step) {
+            fp_volume += fp_step;
+            sound_set_volume(fp_volume >> 8);
+            if (update_func)
+            {
+                update_func();
+            }
+            sleep(1);
+        }
+        sound_set_volume(global_settings.volume);
+    }
+    else {
+        /* fade out */
+        int fp_volume = fp_global_vol;
+
+        while (fp_volume > fp_min_vol + fp_step) {
+            fp_volume -= fp_step;
+            sound_set_volume(fp_volume >> 8);
+            if (update_func)
+            {
+                update_func();
+            }
+            sleep(1);
+        }
+        audio_pause();
+#if CONFIG_CODEC != SWCODEC
+#ifndef SIMULATOR
+        /* let audio thread run and wait for the mas to run out of data */
+        while (!mp3_pause_done())
+#endif
+            sleep(HZ/10);
+#endif
+
+        /* reset volume to what it was before the fade */
+        sound_set_volume(global_settings.volume);
+    }
+}
+
 void audio_pause(void)
 {
     LOGFQUEUE("audio >| audio Q_AUDIO_PAUSE");
diff --git a/apps/playback.h b/apps/playback.h
index 378d5ef..0bfa37d 100644
--- a/apps/playback.h
+++ b/apps/playback.h
@@ -35,6 +35,7 @@ void audio_pre_ff_rewind(void);
 void audio_set_crossfade(int type);
 void audio_skip(int direction);
 void audio_hard_stop(void); /* Stops audio from serving playback */
+void playback_fade_on_pause(bool fade_in, void (*update_func)(void));

 enum
 {
diff --git a/apps/plugin.c b/apps/plugin.c
index d66cccb..4938afb 100644
--- a/apps/plugin.c
+++ b/apps/plugin.c
@@ -666,7 +666,7 @@ static const struct plugin_api rockbox_api = {
     appsversion,
     /* new stuff at the end, sort into place next time
        the API gets incompatible */
-
+    playback_fade_on_pause,
 };

 int plugin_load(const char* plugin, const void* parameter)
diff --git a/apps/plugin.h b/apps/plugin.h
index 9413a38..3fe6c9d 100644
--- a/apps/plugin.h
+++ b/apps/plugin.h
@@ -834,6 +834,7 @@ struct plugin_api {
     const char *appsversion;
     /* new stuff at the end, sort into place next time
        the API gets incompatible */
+    void (*playback_fade_on_pause)(bool fade_in, void(*update_cb)(void));
 };

 /* plugin header */
diff --git a/apps/plugins/lib/playback_control.c b/apps/plugins/lib/playback_control.c
index 7c28230..fb7c8c8 100644
--- a/apps/plugins/lib/playback_control.c
+++ b/apps/plugins/lib/playback_control.c
@@ -42,9 +42,19 @@ static bool play(void)
         }
     }
     else if (audio_status & AUDIO_STATUS_PAUSE)
-        rb->audio_resume();
+    {
+        if (rb->global_settings->fade_on_stop)
+            rb->playback_fade_on_pause(true, NULL);
+        else
+            rb->audio_resume();
+    }
     else
-        rb->audio_pause();
+    {
+        if (rb->global_settings->fade_on_stop)
+            rb->playback_fade_on_pause(false, NULL);
+        else
+            rb->audio_pause();
+    }
     return false;
 }