Skip to content
This repository
Browse code

Merge pull request #2218 from fritsch/ae-fix-enumerate

AE: Some additional fixes since yesterdays merge
  • Loading branch information...
commit b0f0f561854d5dc04f60a165c96339778c9c3d93 2 parents 0953b45 + d168a60
Martijn Kaijser authored February 14, 2013
103  xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp
@@ -59,7 +59,6 @@ CSoftAE::CSoftAE():
59 59
   m_audiophile         (true        ),
60 60
   m_running            (false       ),
61 61
   m_reOpen             (false       ),
62  
-  m_closeSink          (false       ),
63 62
   m_sinkIsSuspended    (false       ),
64 63
   m_isSuspended        (false       ),
65 64
   m_softSuspend        (false       ),
@@ -190,8 +189,6 @@ void CSoftAE::InternalCloseSink()
190 189
     delete m_sink;
191 190
     m_sink = NULL;
192 191
   }
193  
-  m_closeSink = false;
194  
-  m_closeEvent.Set();
195 192
 }
196 193
 /* this must NEVER be called from outside the main thread or Initialization */
197 194
 void CSoftAE::InternalOpenSink()
@@ -733,7 +730,8 @@ void CSoftAE::PauseStream(CSoftAEStream *stream)
733 730
   stream->m_paused = true;
734 731
   streamLock.Leave();
735 732
 
736  
-  OpenSink();
  733
+  m_reOpen = true;
  734
+  m_wake.Set();
737 735
 }
738 736
 
739 737
 void CSoftAE::ResumeStream(CSoftAEStream *stream)
@@ -744,7 +742,8 @@ void CSoftAE::ResumeStream(CSoftAEStream *stream)
744 742
   streamLock.Leave();
745 743
 
746 744
   m_streamsPlaying = true;
747  
-  OpenSink();
  745
+  m_reOpen = true;
  746
+  m_wake.Set();
748 747
 }
749 748
 
750 749
 void CSoftAE::Stop()
@@ -781,7 +780,7 @@ IAEStream *CSoftAE::MakeStream(enum AEDataFormat dataFormat, unsigned int sample
781 780
   CSoftAEStream *stream = new CSoftAEStream(dataFormat, sampleRate, encodedSampleRate, channelLayout, options);
782 781
   m_newStreams.push_back(stream);
783 782
   streamLock.Leave();
784  
-
  783
+  // this is really needed here
785 784
   OpenSink();
786 785
   return stream;
787 786
 }
@@ -873,18 +872,9 @@ IAEStream *CSoftAE::FreeStream(IAEStream *stream)
873 872
   CSingleLock lock(m_streamLock);
874 873
   RemoveStream(m_playingStreams, (CSoftAEStream*)stream);
875 874
   RemoveStream(m_streams       , (CSoftAEStream*)stream);
876  
-  lock.Leave();
877  
-  // Close completely when we go to suspend, reopen as it was old behaviour.
878  
-  // Not opening when masterstream stops means clipping on S/PDIF.
879  
-  if(m_isSuspended)
880  
-  {
881  
-    m_closeEvent.Reset();
882  
-    m_closeSink = true;
883  
-    m_closeEvent.Wait();
884  
-    m_wake.Set();
885  
-  }
886  
-  else if (m_masterStream == stream)
887  
-	  OpenSink();
  875
+  // Reopen is old behaviour. Not opening when masterstream stops means clipping on S/PDIF.
  876
+  if(!m_isSuspended && (m_masterStream == stream))
  877
+    m_reOpen = true;
888 878
 
889 879
   delete (CSoftAEStream*)stream;
890 880
   return NULL;
@@ -990,32 +980,45 @@ bool CSoftAE::Suspend()
990 980
     CSoftAEStream *stream = *itt;
991 981
     stream->Flush();
992 982
   }
  983
+  streamLock.Leave();
993 984
   #if defined(TARGET_LINUX)
994 985
   /*workaround sinks not playing sound after resume */
995 986
     StopAllSounds();
996  
-    CExclusiveLock sinkLock(m_sinkLock);
997  
-    for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
998  
-    {
999  
-      itt->m_deviceInfoList.pop_back();
1000  
-    }
  987
+    bool ret = true;
1001 988
     if(m_sink)
1002 989
     {
1003 990
       /* Deinitialize and delete current m_sink */
1004 991
       // we don't want that Run reopens our device, so we wait.
1005 992
       m_saveSuspend.Reset();
1006 993
       // wait until we are looping in ProcessSuspend()
1007  
-      m_saveSuspend.Wait();
1008  
-      m_sink->Drain();
1009  
-      m_sink->Deinitialize();
1010  
-      delete m_sink;
1011  
-      m_sink = NULL;
1012  
-      // signal anybody, that the sink is closed now
1013  
-      // this should help us not to run into deadlocks
1014  
-      if(m_closeSink)
1015  
-       m_closeEvent.Set();
  994
+      // this is more save to not come up unclean
  995
+      // we cannot wait forever
  996
+      ret = m_saveSuspend.WaitMSec(500);
  997
+      if(ret)
  998
+      {
  999
+        CLog::Log(LOGDEBUG, "CSoftAE::Suspend - After Event");
  1000
+        CExclusiveLock sinkLock(m_sinkLock);
  1001
+        // remove all the sinks
  1002
+        for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
  1003
+        {
  1004
+          itt->m_deviceInfoList.pop_back();
  1005
+        }
  1006
+        InternalCloseSink();
  1007
+      }
  1008
+      else
  1009
+      {
  1010
+        CLog::Log(LOGDEBUG, "CSoftAE::Suspend - Unload failed will continue");
  1011
+        m_saveSuspend.Reset();
  1012
+      }
1016 1013
     }
1017 1014
     // The device list is now empty and must be reenumerated afterwards.
1018  
-    m_sinkInfoList.clear();
  1015
+    if(ret)
  1016
+      m_sinkInfoList.clear();
  1017
+
  1018
+    // signal anybody, that we are gone now (beware of deadlocks)
  1019
+    // we don't unset the fields here, to care for reinit after resume
  1020
+    if(m_reOpen)
  1021
+      m_reOpenEvent.Set();
1019 1022
   #endif
1020 1023
 
1021 1024
   return true;
@@ -1025,7 +1028,7 @@ bool CSoftAE::Resume()
1025 1028
 {
1026 1029
 #if defined(TARGET_LINUX)
1027 1030
   // We must make sure, that we don't return empty.
1028  
-  if(m_isSuspended || m_sinkInfoList.empty())
  1031
+  if(m_sinkInfoList.empty())
1029 1032
   {
1030 1033
     CLog::Log(LOGDEBUG, "CSoftAE::Resume - Re Enumerating Sinks");
1031 1034
     CExclusiveLock sinkLock(m_sinkLock);
@@ -1054,21 +1057,12 @@ void CSoftAE::Run()
1054 1057
   {
1055 1058
     bool restart = false;
1056 1059
 
1057  
-    /* Clean Up what the suspend guy might have forgotten */
1058  
-    // ProcessSuspending() cannot guarantee that we get our sink back softresumed
1059  
-    // that is a big problem as another thread could start adding packets
1060  
-    // this must be checked here, before writing anything on the sinks
1061  
-    if(m_sinkIsSuspended)
1062  
-    {
1063  
-    	CLog::Log(LOGDEBUG, "CSoftAE::Run - Someone has forgotten to resume us (device resumed)");
1064  
-    	m_sink->SoftResume();
1065  
-    	m_sinkIsSuspended = false;
1066  
-    }
1067  
-    if ((this->*m_outputStageFn)(hasAudio) > 0)
  1060
+    /* with the new non blocking implementation - we just reOpen here, when it tells reOpen */
  1061
+    if (!m_reOpen && (this->*m_outputStageFn)(hasAudio) > 0)
1068 1062
       hasAudio = false; /* taken some audio - reset our silence flag */
1069 1063
 
1070 1064
     /* if we have enough room in the buffer */
1071  
-    if (m_buffer.Free() >= m_frameSize)
  1065
+    if (!m_reOpen && m_buffer.Free() >= m_frameSize)
1072 1066
     {
1073 1067
       /* take some data for our use from the buffer */
1074 1068
       uint8_t *out = (uint8_t*)m_buffer.Take(m_frameSize);
@@ -1084,18 +1078,19 @@ void CSoftAE::Run()
1084 1078
         restart = true;
1085 1079
     }
1086 1080
 
1087  
-    //we are told to close the sink
1088  
-    if(m_closeSink)
1089  
-    {
1090  
-      InternalCloseSink();
1091  
-    }
1092  
-
1093 1081
     /* Handle idle or forced suspend */
1094 1082
     ProcessSuspend();
1095 1083
 
1096 1084
     /* if we are told to restart */
1097 1085
     if (m_reOpen || restart || !m_sink)
1098 1086
     {
  1087
+      if(m_sinkIsSuspended && m_sink)
  1088
+      {
  1089
+        // hint for fritsch: remember lazy evaluation
  1090
+        m_reOpen = !m_sink->SoftResume() || m_reOpen;
  1091
+        m_sinkIsSuspended = false;
  1092
+        CLog::Log(LOGDEBUG, "CSoftAE::Run - Sink was forgotten");   
  1093
+      }
1099 1094
       CLog::Log(LOGDEBUG, "CSoftAE::Run - Sink restart flagged");
1100 1095
       InternalOpenSink();
1101 1096
     }
@@ -1373,7 +1368,6 @@ unsigned int CSoftAE::RunRawStreamStage(unsigned int channelCount, void *out, bo
1373 1368
   StreamList resumeStreams;
1374 1369
   static StreamList::iterator itt;
1375 1370
   CSingleLock streamLock(m_streamLock);
1376  
-
1377 1371
   /* handle playing streams */
1378 1372
   for (itt = m_playingStreams.begin(); itt != m_playingStreams.end(); ++itt)
1379 1373
   {
@@ -1483,7 +1477,6 @@ inline void CSoftAE::RemoveStream(StreamList &streams, CSoftAEStream *stream)
1483 1477
 
1484 1478
 inline void CSoftAE::ProcessSuspend()
1485 1479
 {
1486  
-  m_sinkIsSuspended = false;
1487 1480
   unsigned int curSystemClock = 0;
1488 1481
 #if defined(TARGET_WINDOWS) || defined(TARGET_LINUX)
1489 1482
   if (!m_softSuspend && m_playingStreams.empty() && m_playing_sounds.empty() &&
@@ -1541,7 +1534,7 @@ inline void CSoftAE::ProcessSuspend()
1541 1534
      */
1542 1535
     if (!m_isSuspended && (!m_playingStreams.empty() || !m_playing_sounds.empty()))
1543 1536
     {
1544  
-      m_reOpen = m_reOpen || !m_sink->SoftResume(); // sink returns false if it requires reinit
  1537
+      m_reOpen = !m_sink->SoftResume() || m_reOpen; // sink returns false if it requires reinit (worthless with current implementation)
1545 1538
       m_sinkIsSuspended = false; //sink processing data
1546 1539
       m_softSuspend   = false; //break suspend loop (under some conditions)
1547 1540
       CLog::Log(LOGDEBUG, "Resumed the Sink");
2  xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h
@@ -137,14 +137,12 @@ class CSoftAE : public IThreadedAE
137 137
 
138 138
   /* internal vars */
139 139
   bool             m_running, m_reOpen;
140  
-  bool             m_closeSink;
141 140
   bool             m_sinkIsSuspended; /* The sink is in unusable state, e.g. SoftSuspended */
142 141
   bool             m_isSuspended;      /* engine suspended by external function to release audio context */
143 142
   bool             m_softSuspend;      /* latches after last stream or sound played for timer below for idle */
144 143
   unsigned int     m_softSuspendTimer; /* time in milliseconds to hold sink open before soft suspend for idle */
145 144
   CEvent           m_reOpenEvent;
146 145
   CEvent           m_wake;
147  
-  CEvent           m_closeEvent;
148 146
   CEvent           m_saveSuspend;
149 147
 
150 148
   CCriticalSection m_runningLock;     /* released when the thread exits */
11  xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
@@ -1144,16 +1144,17 @@ bool CAESinkALSA::SoftSuspend()
1144 1144
 }
1145 1145
 bool CAESinkALSA::SoftResume()
1146 1146
 {
1147  
-	// reinit all the clibber
  1147
+    // reinit all the clibber
  1148
+    bool ret = true; // all fine
1148 1149
     if(!m_pcm)
1149 1150
     {
1150 1151
       if (!snd_config)
1151  
-	    snd_config_update();
  1152
+        snd_config_update();
1152 1153
 
1153  
-      Initialize(m_initFormat, m_initDevice);
  1154
+      ret = Initialize(m_initFormat, m_initDevice);
1154 1155
     }
1155  
-   //we want that AE loves us again
1156  
-   return false; // force reinit
  1156
+   //we want that AE loves us again - reinit when initialize failed
  1157
+   return ret; // force reinit if false
1157 1158
 }
1158 1159
 
1159 1160
 void CAESinkALSA::sndLibErrorHandler(const char *file, int line, const char *function, int err, const char *fmt, ...)

0 notes on commit b0f0f56

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