Skip to content
This repository
Browse code

Merge pull request #1548 from DDDamian/SoftSuspendSink

[AE] Allow sink to decide how or if it can be suspended
  • Loading branch information...
commit f528cd3cb7a393dcca1b88f965b7838f1edad51e 2 parents cd5a8c3 + 2b41991
davilla authored November 29, 2012
78  xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp
@@ -1017,34 +1017,8 @@ void CSoftAE::Run()
1017 1017
         restart = true;
1018 1018
     }
1019 1019
 
1020  
-    if (m_playingStreams.empty() && m_playing_sounds.empty() && m_streams.empty() && 
1021  
-       !m_softSuspend && !g_advancedSettings.m_streamSilence)
1022  
-    {
1023  
-      m_softSuspend = true;
1024  
-      m_softSuspendTimer = XbmcThreads::SystemClockMillis() + 10000; //10.0 second delay for softSuspend
1025  
-    }
1026  
-
1027  
-    unsigned int curSystemClock = XbmcThreads::SystemClockMillis();
1028  
-
1029  
-    /* idle while in Suspend() state until Resume() called */
1030  
-    /* idle if nothing to play and user hasn't enabled     */
1031  
-    /* continuous streaming (silent stream) in as.xml      */
1032  
-    while ((m_isSuspended || (m_softSuspend && (curSystemClock > m_softSuspendTimer))) &&
1033  
-            m_running     && !m_reOpen      && !restart)
1034  
-    {
1035  
-      if (m_sink)
1036  
-      {
1037  
-        /* take the sink lock */
1038  
-        CExclusiveLock sinkLock(m_sinkLock);
1039  
-        //m_sink->Drain(); TODO: implement
1040  
-        m_sink->Deinitialize();
1041  
-        delete m_sink;
1042  
-        m_sink = NULL;
1043  
-      }
1044  
-      if (!m_playingStreams.empty() || !m_playing_sounds.empty() || !m_sounds.empty())
1045  
-        m_softSuspend = false;
1046  
-      m_wake.WaitMSec(SOFTAE_IDLE_WAIT_MSEC);
1047  
-    }
  1020
+    /* Handle idle or forced suspend */
  1021
+    ProcessSuspend();
1048 1022
 
1049 1023
     /* if we are told to restart */
1050 1024
     if (m_reOpen || restart || !m_sink)
@@ -1405,3 +1379,51 @@ inline void CSoftAE::RemoveStream(StreamList &streams, CSoftAEStream *stream)
1405 1379
     m_streamsPlaying = !m_playingStreams.empty();
1406 1380
 }
1407 1381
 
  1382
+inline void CSoftAE::ProcessSuspend()
  1383
+{
  1384
+  bool sinkIsSuspended = false;
  1385
+
  1386
+  if (m_playingStreams.empty() && m_playing_sounds.empty() && 
  1387
+     !m_softSuspend && !g_advancedSettings.m_streamSilence)
  1388
+  {
  1389
+    m_softSuspend = true;
  1390
+    m_softSuspendTimer = XbmcThreads::SystemClockMillis() + 10000; //10.0 second delay for softSuspend
  1391
+  }
  1392
+
  1393
+  unsigned int curSystemClock = XbmcThreads::SystemClockMillis();
  1394
+
  1395
+  /* idle while in Suspend() state until Resume() called */
  1396
+  /* idle if nothing to play and user hasn't enabled     */
  1397
+  /* continuous streaming (silent stream) in as.xml      */
  1398
+  while ((m_isSuspended || (m_softSuspend && (curSystemClock > m_softSuspendTimer))) &&
  1399
+          m_running     && !m_reOpen)
  1400
+  {
  1401
+    if (m_sink && !sinkIsSuspended)
  1402
+    {
  1403
+      /* put the sink in Suspend mode */
  1404
+      CExclusiveLock sinkLock(m_sinkLock);
  1405
+      if (!m_sink->SoftSuspend())
  1406
+      {
  1407
+        sinkIsSuspended = false; //sink cannot be suspended
  1408
+        m_softSuspend   = false; //break suspend loop
  1409
+        break;
  1410
+      }
  1411
+      else
  1412
+        sinkIsSuspended = true; //sink has suspended processing
  1413
+      sinkLock.Leave();
  1414
+    }
  1415
+
  1416
+    /* idle for platform-defined time */
  1417
+    m_wake.WaitMSec(SOFTAE_IDLE_WAIT_MSEC);
  1418
+
  1419
+    /* check if we need to resume for stream or sound */
  1420
+    if (!m_isSuspended && (!m_playingStreams.empty() || !m_playing_sounds.empty()))
  1421
+    {
  1422
+      m_reOpen = !m_sink->SoftResume(); // sink returns false if it requires reinit
  1423
+      sinkIsSuspended = false; //sink processing data
  1424
+      m_softSuspend   = false; //break suspend loop
  1425
+      break;
  1426
+    }
  1427
+  }
  1428
+}
  1429
+
9  xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h
@@ -120,6 +120,8 @@ class CSoftAE : public IThreadedAE
120 120
   bool SetupEncoder(AEAudioFormat &format);
121 121
   void Deinitialize();
122 122
 
  123
+  inline void ProcessSuspend(); /* enter suspend state if nothing to play and sink allows */
  124
+
123 125
   inline void GetDeviceFriendlyName(std::string &device);
124 126
 
125 127
   IAESink *GetSink(AEAudioFormat &desiredFormat, bool passthrough, std::string &device);
@@ -133,9 +135,10 @@ class CSoftAE : public IThreadedAE
133 135
   bool m_stereoUpmix;
134 136
 
135 137
   /* internal vars */
136  
-  bool             m_running, m_reOpen, m_isSuspended;
137  
-  bool             m_softSuspend;      /* latches after last stream or sound played for timer below */
138  
-  unsigned int     m_softSuspendTimer; /* time in milliseconds to hold sink open before soft suspend */
  138
+  bool             m_running, m_reOpen;
  139
+  bool             m_isSuspended;      /* engine suspended by external function to release audio context */
  140
+  bool             m_softSuspend;      /* latches after last stream or sound played for timer below for idle */
  141
+  unsigned int     m_softSuspendTimer; /* time in milliseconds to hold sink open before soft suspend for idle */
139 142
   CEvent           m_reOpenEvent;
140 143
   CEvent           m_wake;
141 144
 
12  xbmc/cores/AudioEngine/Interfaces/AESink.h
@@ -87,5 +87,17 @@ class IAESink
87 87
     This method sets the volume control, volume ranges from 0.0 to 1.0.
88 88
   */
89 89
   virtual void  SetVolume(float volume) {};
  90
+
  91
+  /*
  92
+    Requests sink to prepare itself for a suspend state
  93
+    @return false if sink cannot be suspended
  94
+  */
  95
+  virtual bool SoftSuspend() {return false;};
  96
+
  97
+  /*
  98
+    Notify sink to prepare to resume processing after suspend state
  99
+    @return false if sink must be reinitialized
  100
+  */
  101
+  virtual bool SoftResume() {return false;};
90 102
 };
91 103
 
6  xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
@@ -489,9 +489,6 @@ unsigned int CAESinkALSA::AddPackets(uint8_t *data, unsigned int frames, bool ha
489 489
   if (!m_pcm)
490 490
     return 0;
491 491
 
492  
-  if (snd_pcm_state(m_pcm) == SND_PCM_STATE_PREPARED)
493  
-    snd_pcm_start(m_pcm);
494  
-
495 492
   int ret;
496 493
 
497 494
   ret = snd_pcm_avail(m_pcm);
@@ -520,6 +517,9 @@ unsigned int CAESinkALSA::AddPackets(uint8_t *data, unsigned int frames, bool ha
520 517
     }
521 518
   }
522 519
 
  520
+  if ( ret > 0 && snd_pcm_state(m_pcm) == SND_PCM_STATE_PREPARED)
  521
+    snd_pcm_start(m_pcm);
  522
+
523 523
   return ret;
524 524
 }
525 525
 
24  xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp
@@ -331,7 +331,8 @@ void CAESinkWASAPI::Deinitialize()
331 331
   {
332 332
     try
333 333
     {
334  
-    m_pAudioClient->Stop();
  334
+    m_pAudioClient->Stop();  //stop the audio output
  335
+    m_pAudioClient->Reset(); //flush buffer and reset audio clock stream position
335 336
     }
336 337
     catch (...)
337 338
     {
@@ -537,6 +538,27 @@ unsigned int CAESinkWASAPI::AddPackets(uint8_t *data, unsigned int frames, bool
537 538
   return NumFramesRequested;
538 539
 }
539 540
 
  541
+bool CAESinkWASAPI::SoftSuspend()
  542
+{
  543
+  /* Sink has been asked to suspend output - we release audio   */
  544
+  /* device as we are in exclusive mode and thus allow external */
  545
+  /* audio sources to play. This requires us to reinitialize    */
  546
+  /* on resume.                                                 */
  547
+
  548
+  Deinitialize();
  549
+
  550
+  return true;
  551
+}
  552
+
  553
+bool CAESinkWASAPI::SoftResume()
  554
+{
  555
+  /* Sink asked to resume output. To release audio device in    */
  556
+  /* exclusive mode we release the device context and therefore */
  557
+  /* must reinitialize. Return false to force re-init by engine */
  558
+
  559
+  return false;
  560
+}
  561
+
540 562
 void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList)
541 563
 {
542 564
   IMMDeviceEnumerator* pEnumerator = NULL;
3  xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h
@@ -43,6 +43,8 @@ class CAESinkWASAPI : public IAESink
43 43
     virtual double       GetCacheTime                ();
44 44
     virtual double       GetCacheTotal               ();
45 45
     virtual unsigned int AddPackets                  (uint8_t *data, unsigned int frames, bool hasAudio);
  46
+    virtual bool         SoftSuspend                 ();
  47
+    virtual bool         SoftResume                  ();
46 48
     static  void         EnumerateDevicesEx          (AEDeviceInfoList &deviceInfoList);
47 49
 private:
48 50
     bool         InitializeExclusive(AEAudioFormat &format);
@@ -70,6 +72,7 @@ class CAESinkWASAPI : public IAESink
70 72
 
71 73
     bool                m_running;
72 74
     bool                m_initialized;
  75
+    bool                m_isSuspended;    /* sink is in a suspended state - release audio device */
73 76
     bool                m_isDirty;        /* sink output failed - needs re-init or new device */
74 77
 
75 78
     unsigned int        m_uiBufferLen;    /* wasapi endpoint buffer size, in frames */

0 notes on commit f528cd3

Please sign in to comment.
Something went wrong with that request. Please try again.