Have voice fire an event when it starts and stops playing.

Further decouples voice_thread.c from other playback areas. Also allows
other audio sources, such as FM radio, to be attenuated when voice is
playing by implementing a callback.

Defined as another playback event rather than a new event class:
PLAYBACK_EVENT_VOICE_PLAYING

Change-Id: I2e3e218be6cd6bebbf39e7883a8c0e4ed42b62bb
diff --git a/apps/appevents.h b/apps/appevents.h
index a11e423..506f003 100644
--- a/apps/appevents.h
+++ b/apps/appevents.h
@@ -45,6 +45,8 @@
     PLAYBACK_EVENT_TRACK_SKIP,
     /* Next track medadata was just loaded */
     PLAYBACK_EVENT_NEXTTRACKID3_AVAILABLE,
+    /* Voice is playing: data = &(bool){true|false} */
+    PLAYBACK_EVENT_VOICE_PLAYING,
 };
 
 /** Buffering events **/
diff --git a/apps/playback.c b/apps/playback.c
index 870cb08..9cc29ea 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -344,6 +344,12 @@
 
 /**************************************/
 
+/** --- voice event --- **/
+void playback_voice_event(void *data)
+{
+    pcmbuf_soft_mode(*(bool *)data);
+}
+
 /** --- audio_queue helpers --- **/
 static void audio_queue_post(long id, intptr_t data)
 {
@@ -3760,6 +3766,7 @@
     mutex_init(&id3_mutex);
     track_list_init();
     buffering_init();
+    add_event(PLAYBACK_EVENT_VOICE_PLAYING, false, playback_voice_event);
 #ifdef HAVE_CROSSFADE
     /* Set crossfade setting for next buffer init which should be about... */
     pcmbuf_request_crossfade_enable(global_settings.crossfade);
diff --git a/apps/voice_thread.c b/apps/voice_thread.c
index e8c7fcc..1fb8c15 100644
--- a/apps/voice_thread.c
+++ b/apps/voice_thread.c
@@ -22,12 +22,10 @@
 #include "system.h"
 #include "core_alloc.h"
 #include "thread.h"
+#include "appevents.h"
 #include "voice_thread.h"
 #include "talk.h"
 #include "dsp_core.h"
-#include "audio.h"
-#include "playback.h"
-#include "pcmbuf.h"
 #include "pcm.h"
 #include "pcm_mixer.h"
 #include "codecs/libspeex/speex/speex.h"
@@ -84,6 +82,7 @@
 static struct event_queue voice_queue SHAREDBSS_ATTR;
 static struct queue_sender_list voice_queue_sender_list SHAREDBSS_ATTR;
 static int quiet_counter SHAREDDATA_ATTR = 0;
+static bool voice_playing = false;
 
 #define VOICE_PCM_FRAME_COUNT   ((NATIVE_FREQUENCY*VOICE_FRAME_COUNT + \
                                  VOICE_SAMPLE_RATE) / VOICE_SAMPLE_RATE)
@@ -301,7 +300,7 @@
 /* Tell if voice is still in a playing state */
 bool mp3_is_playing(void)
 {
-    return quiet_counter != 0;
+    return voice_playing;
 }
 
 /* This function is meant to be used by the buffer request functions to
@@ -319,7 +318,7 @@
      * new clip by the time we wait. This should be resolvable if conditions
      * ever require knowing the very clip you requested has finished. */
 
-    while (quiet_counter != 0)
+    while (voice_playing)
         sleep(1);
 }
 
@@ -341,10 +340,8 @@
 /* Voice thread message processing */
 static enum voice_state voice_message(struct voice_thread_data *td)
 {
-    if (quiet_counter > 0)
-        queue_wait_w_tmo(&voice_queue, &td->ev, HZ/10);
-    else
-        queue_wait(&voice_queue, &td->ev);
+    queue_wait_w_tmo(&voice_queue, &td->ev,
+                     quiet_counter > 0 ? HZ/10 : TIMEOUT_BLOCK);
 
     switch (td->ev.id)
     {
@@ -361,6 +358,14 @@
             voice_stop_playback();
         }
 
+        if (quiet_counter <= 0)
+        {
+            /* Make audio play more softly and set delay to return to normal
+               playback level */
+            voice_playing = true;
+            send_event(PLAYBACK_EVENT_VOICE_PLAYING, &voice_playing);
+        }
+
         quiet_counter = QUIET_COUNT;
 
         /* Copy the clip info */
@@ -369,10 +374,6 @@
         /* We need nothing more from the sending thread - let it run */
         queue_reply(&voice_queue, 1);
 
-        /* Make audio play more softly and set delay to return to normal
-           playback level */
-        pcmbuf_soft_mode(true);
-
         /* Clean-start the decoder */
         td->st = speex_decoder_init(&speex_wb_mode);
 
@@ -394,8 +395,10 @@
         if (quiet_counter-- != QUIET_COUNT)
         {
             if (quiet_counter <= 0)
-                pcmbuf_soft_mode(false);
-
+            {
+                voice_playing = false;
+                send_event(PLAYBACK_EVENT_VOICE_PLAYING, &voice_playing);
+            }
             break;
         }