Skip to content
This repository
Browse code

Merge pull request #2152 from fritsch/ae-fix-proposal

AE: make forced enumeration possible
  • Loading branch information...
commit 3cfc1c8e2896a537d6c4c1ecd815d4cb6e6a76e6 2 parents 2ba85f9 + cc49b02
davilla authored February 09, 2013
10  xbmc/cores/AudioEngine/AESinkFactory.cpp
@@ -129,15 +129,15 @@ IAESink *CAESinkFactory::Create(std::string &device, AEAudioFormat &desiredForma
129 129
   return NULL;
130 130
 }
131 131
 
132  
-#define ENUMERATE_SINK(SINK) { \
  132
+#define ENUMERATE_SINK(SINK, force) { \
133 133
   AESinkInfo info; \
134 134
   info.m_sinkName = #SINK; \
135  
-  CAESink ##SINK::EnumerateDevicesEx(info.m_deviceInfoList); \
  135
+  CAESink ##SINK::EnumerateDevicesEx(info.m_deviceInfoList, force); \
136 136
   if(!info.m_deviceInfoList.empty()) \
137 137
     list.push_back(info); \
138 138
 }
139 139
 
140  
-void CAESinkFactory::EnumerateEx(AESinkInfoList &list)
  140
+void CAESinkFactory::EnumerateEx(AESinkInfoList &list, bool force)
141 141
 {
142 142
 #if defined(TARGET_WINDOWS)
143 143
   ENUMERATE_SINK(DirectSound);
@@ -147,10 +147,10 @@ void CAESinkFactory::EnumerateEx(AESinkInfoList &list)
147 147
     ENUMERATE_SINK(AUDIOTRACK);
148 148
 #elif defined(TARGET_LINUX) || defined(TARGET_FREEBSD)
149 149
   #if defined(HAS_ALSA)
150  
-    ENUMERATE_SINK(ALSA);
  150
+    ENUMERATE_SINK(ALSA, force);
151 151
   #endif
152 152
 
153  
-    ENUMERATE_SINK(OSS);
  153
+    ENUMERATE_SINK(OSS, force);
154 154
 #endif
155 155
 
156 156
 }
2  xbmc/cores/AudioEngine/AESinkFactory.h
@@ -40,6 +40,6 @@ class CAESinkFactory
40 40
 public:
41 41
   static void     ParseDevice(std::string &device, std::string &driver);
42 42
   static IAESink *Create(std::string &device, AEAudioFormat &desiredFormat, bool rawPassthrough);
43  
-  static void     EnumerateEx(AESinkInfoList &list);
  43
+  static void     EnumerateEx(AESinkInfoList &list, bool force = false); /* The force flag can be used to indicate the rescan devices */
44 44
 };
45 45
 
183  xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.cpp
@@ -59,6 +59,8 @@ CSoftAE::CSoftAE():
59 59
   m_audiophile         (true        ),
60 60
   m_running            (false       ),
61 61
   m_reOpen             (false       ),
  62
+  m_closeSink          (false       ),
  63
+  m_sinkIsSuspended    (false       ),
62 64
   m_isSuspended        (false       ),
63 65
   m_softSuspend        (false       ),
64 66
   m_softSuspendTimer   (0           ),
@@ -74,21 +76,18 @@ CSoftAE::CSoftAE():
74 76
   m_outputStageFn      (NULL        ),
75 77
   m_streamStageFn      (NULL        )
76 78
 {
  79
+  unsigned int c_retry = 5;
77 80
   CAESinkFactory::EnumerateEx(m_sinkInfoList);
78  
-  for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
  81
+  while(m_sinkInfoList.size() == 0 && c_retry > 0)
79 82
   {
80  
-    CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str());
81  
-    int count = 0;
82  
-    for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
83  
-    {
84  
-      CLog::Log(LOGNOTICE, "    Device %d", ++count);
85  
-      CAEDeviceInfo& info = *itt2;
86  
-      std::stringstream ss((std::string)info);
87  
-      std::string line;
88  
-      while(std::getline(ss, line, '\n'))
89  
-        CLog::Log(LOGNOTICE, "        %s", line.c_str());
90  
-    }
  83
+    CLog::Log(LOGNOTICE, "No Devices found - retry: %d", c_retry);
  84
+    Sleep(2000);
  85
+    c_retry--;
  86
+    // retry the enumeration
  87
+    CAESinkFactory::EnumerateEx(m_sinkInfoList, true);
91 88
   }
  89
+  CLog::Log(LOGNOTICE, "Found %lu Lists of Devices", m_sinkInfoList.size());
  90
+  PrintSinks();
92 91
 }
93 92
 
94 93
 CSoftAE::~CSoftAE()
@@ -179,6 +178,20 @@ void CSoftAE::OpenSink()
179 178
   m_wake.Set();
180 179
 }
181 180
 
  181
+void CSoftAE::InternalCloseSink()
  182
+{
  183
+  /* close the old sink if it was open */
  184
+  if (m_sink)
  185
+  {
  186
+    CExclusiveLock sinkLock(m_sinkLock);
  187
+    m_sink->Drain();
  188
+    m_sink->Deinitialize();
  189
+    delete m_sink;
  190
+    m_sink = NULL;
  191
+  }
  192
+  m_closeSink = false;
  193
+  m_closeEvent.Set();
  194
+}
182 195
 /* this must NEVER be called from outside the main thread or Initialization */
183 196
 void CSoftAE::InternalOpenSink()
184 197
 {
@@ -305,15 +318,8 @@ void CSoftAE::InternalOpenSink()
305 318
     CExclusiveLock sinkLock(m_sinkLock);
306 319
 
307 320
     reInit = true;
308  
-
309  
-    /* we are going to open, so close the old sink if it was open */
310  
-    if (m_sink)
311  
-    {
312  
-      m_sink->Drain();
313  
-      m_sink->Deinitialize();
314  
-      delete m_sink;
315  
-      m_sink = NULL;
316  
-    }
  321
+    //close the sink cause it gets reinited
  322
+    InternalCloseSink();
317 323
 
318 324
     /* get the display name of the device */
319 325
     GetDeviceFriendlyName(device);
@@ -867,10 +873,17 @@ IAEStream *CSoftAE::FreeStream(IAEStream *stream)
867 873
   RemoveStream(m_playingStreams, (CSoftAEStream*)stream);
868 874
   RemoveStream(m_streams       , (CSoftAEStream*)stream);
869 875
   lock.Leave();
870  
-
871  
-  /* if it was the master stream we need to reopen before deletion */
872  
-  if (m_masterStream == stream)
873  
-    OpenSink();
  876
+  // Close completely when we go to suspend, reopen as it was old behaviour.
  877
+  // Not opening when masterstream stops means clipping on S/PDIF.
  878
+  if(m_isSuspended)
  879
+  {
  880
+    m_closeEvent.Reset();
  881
+    m_closeSink = true;
  882
+    m_closeEvent.Wait();
  883
+    m_wake.Set();
  884
+  }
  885
+  else if (m_masterStream == stream)
  886
+	  OpenSink();
874 887
 
875 888
   delete (CSoftAEStream*)stream;
876 889
   return NULL;
@@ -976,14 +989,54 @@ bool CSoftAE::Suspend()
976 989
     CSoftAEStream *stream = *itt;
977 990
     stream->Flush();
978 991
   }
  992
+  #if defined(TARGET_LINUX)
  993
+  /*workaround sinks not playing sound after resume */
  994
+    StopAllSounds();
  995
+    CExclusiveLock sinkLock(m_sinkLock);
  996
+    for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
  997
+    {
  998
+      itt->m_deviceInfoList.pop_back();
  999
+    }
  1000
+    if(m_sink)
  1001
+    {
  1002
+      /* Deinitialize and delete current m_sink */
  1003
+      // we don't want that Run reopens our device, so we wait.
  1004
+      m_saveSuspend.Reset();
  1005
+      // wait until we are looping in ProcessSuspend()
  1006
+      m_saveSuspend.Wait();
  1007
+      m_sink->Drain();
  1008
+      m_sink->Deinitialize();
  1009
+      delete m_sink;
  1010
+      m_sink = NULL;
  1011
+      // signal anybody, that the sink is closed now
  1012
+      // this should help us not to run into deadlocks
  1013
+      if(m_closeSink)
  1014
+       m_closeEvent.Set();
  1015
+    }
  1016
+    // The device list is now empty and must be reenumerated afterwards.
  1017
+    m_sinkInfoList.clear();
  1018
+  #endif
979 1019
 
980 1020
   return true;
981 1021
 }
982 1022
 
983 1023
 bool CSoftAE::Resume()
984 1024
 {
  1025
+#if defined(TARGET_LINUX)
  1026
+  // We must make sure, that we don't return empty.
  1027
+  if(m_isSuspended || m_sinkInfoList.empty())
  1028
+  {
  1029
+    CLog::Log(LOGDEBUG, "CSoftAE::Resume - Re Enumerating Sinks");
  1030
+    CExclusiveLock sinkLock(m_sinkLock);
  1031
+    // Forced enumeration - we are sure that we start completely fresh.
  1032
+    CAESinkFactory::EnumerateEx(m_sinkInfoList, true);
  1033
+    sinkLock.Leave(); // we leave here explicitly to not lock while printing new sinks
  1034
+    PrintSinks();
  1035
+  }
  1036
+#endif
985 1037
   CLog::Log(LOGDEBUG, "CSoftAE::Resume - Resuming AE processing");
986 1038
   m_isSuspended = false;
  1039
+  // we flag reopen
987 1040
   m_reOpen = true;
988 1041
 
989 1042
   return true;
@@ -1000,6 +1053,16 @@ void CSoftAE::Run()
1000 1053
   {
1001 1054
     bool restart = false;
1002 1055
 
  1056
+    /* Clean Up what the suspend guy might have forgotten */
  1057
+    // ProcessSuspending() cannot guarantee that we get our sink back softresumed
  1058
+    // that is a big problem as another thread could start adding packets
  1059
+    // this must be checked here, before writing anything on the sinks
  1060
+    if(m_sinkIsSuspended)
  1061
+    {
  1062
+    	CLog::Log(LOGDEBUG, "CSoftAE::Run - Someone has forgotten to resume us (device resumed)");
  1063
+    	m_sink->SoftResume();
  1064
+    	m_sinkIsSuspended = false;
  1065
+    }
1003 1066
     if ((this->*m_outputStageFn)(hasAudio) > 0)
1004 1067
       hasAudio = false; /* taken some audio - reset our silence flag */
1005 1068
 
@@ -1020,6 +1083,12 @@ void CSoftAE::Run()
1020 1083
         restart = true;
1021 1084
     }
1022 1085
 
  1086
+    //we are told to close the sink
  1087
+    if(m_closeSink)
  1088
+    {
  1089
+      InternalCloseSink();
  1090
+    }
  1091
+
1023 1092
     /* Handle idle or forced suspend */
1024 1093
     ProcessSuspend();
1025 1094
 
@@ -1028,8 +1097,8 @@ void CSoftAE::Run()
1028 1097
     {
1029 1098
       CLog::Log(LOGDEBUG, "CSoftAE::Run - Sink restart flagged");
1030 1099
       InternalOpenSink();
1031  
-      m_isSuspended = false; // exit Suspend state
1032 1100
     }
  1101
+
1033 1102
 #if defined(TARGET_ANDROID)
1034 1103
     else if (m_playingStreams.empty() 
1035 1104
       &&     m_playing_sounds.empty()
@@ -1280,6 +1349,24 @@ int CSoftAE::RunTranscodeStage(bool hasAudio)
1280 1349
   return encodedFrames;
1281 1350
 }
1282 1351
 
  1352
+void CSoftAE::PrintSinks()
  1353
+{
  1354
+  for (AESinkInfoList::iterator itt = m_sinkInfoList.begin(); itt != m_sinkInfoList.end(); ++itt)
  1355
+  {
  1356
+    CLog::Log(LOGNOTICE, "Enumerated %s devices:", itt->m_sinkName.c_str());
  1357
+    int count = 0;
  1358
+    for (AEDeviceInfoList::iterator itt2 = itt->m_deviceInfoList.begin(); itt2 != itt->m_deviceInfoList.end(); ++itt2)
  1359
+    {
  1360
+      CLog::Log(LOGNOTICE, "    Device %d", ++count);
  1361
+      CAEDeviceInfo& info = *itt2;
  1362
+      std::stringstream ss((std::string)info);
  1363
+      std::string line;
  1364
+      while(std::getline(ss, line, '\n'))
  1365
+        CLog::Log(LOGNOTICE, "        %s", line.c_str());
  1366
+    }
  1367
+  }
  1368
+}
  1369
+
1283 1370
 unsigned int CSoftAE::RunRawStreamStage(unsigned int channelCount, void *out, bool &restart)
1284 1371
 {
1285 1372
   StreamList resumeStreams;
@@ -1395,10 +1482,9 @@ inline void CSoftAE::RemoveStream(StreamList &streams, CSoftAEStream *stream)
1395 1482
 
1396 1483
 inline void CSoftAE::ProcessSuspend()
1397 1484
 {
1398  
-  bool sinkIsSuspended = false;
  1485
+  m_sinkIsSuspended = false;
1399 1486
   unsigned int curSystemClock = 0;
1400  
-
1401  
-#if defined(TARGET_WINDOWS)
  1487
+#if defined(TARGET_WINDOWS) || defined(TARGET_LINUX)
1402 1488
   if (!m_softSuspend && m_playingStreams.empty() && m_playing_sounds.empty() &&
1403 1489
       !g_advancedSettings.m_streamSilence)
1404 1490
   {
@@ -1410,37 +1496,54 @@ inline void CSoftAE::ProcessSuspend()
1410 1496
   if (m_softSuspend)
1411 1497
     curSystemClock = XbmcThreads::SystemClockMillis();
1412 1498
 #endif
1413  
-
1414 1499
   /* idle while in Suspend() state until Resume() called */
1415 1500
   /* idle if nothing to play and user hasn't enabled     */
1416 1501
   /* continuous streaming (silent stream) in as.xml      */
1417  
-  while ((m_isSuspended || (m_softSuspend && (curSystemClock > m_softSuspendTimer))) &&
1418  
-          m_running     && !m_reOpen)
  1502
+  /* In case of Suspend stay in there until Resume is called from outer thread */
  1503
+  while (m_isSuspended || ((m_softSuspend && (curSystemClock > m_softSuspendTimer)) &&
  1504
+          m_running     && !m_reOpen))
1419 1505
   {
1420  
-    if (m_sink && !sinkIsSuspended)
  1506
+    if (!m_isSuspended && m_sink && !m_sinkIsSuspended)
1421 1507
     {
1422 1508
       /* put the sink in Suspend mode */
1423 1509
       CExclusiveLock sinkLock(m_sinkLock);
1424  
-      if (!m_sink->SoftSuspend())
  1510
+      if (m_sink && !m_sink->SoftSuspend())
1425 1511
       {
1426  
-        sinkIsSuspended = false; //sink cannot be suspended
  1512
+        m_sinkIsSuspended = false; //sink cannot be suspended
1427 1513
         m_softSuspend   = false; //break suspend loop
1428 1514
         break;
1429 1515
       }
1430 1516
       else
1431  
-        sinkIsSuspended = true; //sink has suspended processing
  1517
+      {
  1518
+        CLog::Log(LOGDEBUG, "Suspended the Sink");
  1519
+        m_sinkIsSuspended = true; //sink has suspended processing
  1520
+      }
1432 1521
       sinkLock.Leave();
1433 1522
     }
  1523
+    // Signal that the Suspend can go on now.
  1524
+    // Idea: Outer thread calls Suspend() - but
  1525
+    // because of AddPackets does not care about locks, we must make
  1526
+    // sure, that our school bus (AE::Run) is currently driving through
  1527
+    // some gas station, before we move away the sink.
  1528
+    if(m_isSuspended)
  1529
+      m_saveSuspend.Set();
1434 1530
 
1435 1531
     /* idle for platform-defined time */
1436 1532
     m_wake.WaitMSec(SOFTAE_IDLE_WAIT_MSEC);
1437 1533
 
1438  
-    /* check if we need to resume for stream or sound */
  1534
+    /* check if we need to resume for stream or sound or somebody wants to open us
  1535
+     * the suspend checks are only there to:
  1536
+     * a) not run out of softSuspend directly when we are sleeping
  1537
+     * b) nail(!) the thread during real Suspend into this method
  1538
+     * Note: It is not enough to check the streams buffer, cause it might not be filled yet
  1539
+     * We have to check after ProcessSuspending() if the sink is still in softsleep and resume it
  1540
+     */
1439 1541
     if (!m_isSuspended && (!m_playingStreams.empty() || !m_playing_sounds.empty()))
1440 1542
     {
1441  
-      m_reOpen = !m_sink->SoftResume(); // sink returns false if it requires reinit
1442  
-      sinkIsSuspended = false; //sink processing data
1443  
-      m_softSuspend   = false; //break suspend loop
  1543
+      m_reOpen = m_reOpen || !m_sink->SoftResume(); // sink returns false if it requires reinit
  1544
+      m_sinkIsSuspended = false; //sink processing data
  1545
+      m_softSuspend   = false; //break suspend loop (under some conditions)
  1546
+      CLog::Log(LOGDEBUG, "Resumed the Sink");
1444 1547
       break;
1445 1548
     }
1446 1549
   }
6  xbmc/cores/AudioEngine/Engines/SoftAE/SoftAE.h
@@ -116,6 +116,7 @@ class CSoftAE : public IThreadedAE
116 116
   void OpenSink();
117 117
 
118 118
   void InternalOpenSink();
  119
+  void InternalCloseSink();
119 120
   void ResetEncoder();
120 121
   bool SetupEncoder(AEAudioFormat &format);
121 122
   void Deinitialize();
@@ -136,11 +137,15 @@ class CSoftAE : public IThreadedAE
136 137
 
137 138
   /* internal vars */
138 139
   bool             m_running, m_reOpen;
  140
+  bool             m_closeSink;
  141
+  bool             m_sinkIsSuspended; /* The sink is in unusable state, e.g. SoftSuspended */
139 142
   bool             m_isSuspended;      /* engine suspended by external function to release audio context */
140 143
   bool             m_softSuspend;      /* latches after last stream or sound played for timer below for idle */
141 144
   unsigned int     m_softSuspendTimer; /* time in milliseconds to hold sink open before soft suspend for idle */
142 145
   CEvent           m_reOpenEvent;
143 146
   CEvent           m_wake;
  147
+  CEvent           m_closeEvent;
  148
+  CEvent           m_saveSuspend;
144 149
 
145 150
   CCriticalSection m_runningLock;     /* released when the thread exits */
146 151
   CCriticalSection m_streamLock;      /* m_streams lock */
@@ -242,5 +247,6 @@ class CSoftAE : public IThreadedAE
242 247
   void         RunNormalizeStage (unsigned int channelCount, void *out, unsigned int mixed);
243 248
 
244 249
   void         RemoveStream(StreamList &streams, CSoftAEStream *stream);
  250
+  void         PrintSinks();
245 251
 };
246 252
 
39  xbmc/cores/AudioEngine/Sinks/AESinkALSA.cpp
@@ -426,7 +426,6 @@ void CAESinkALSA::Deinitialize()
426 426
 
427 427
   if (m_pcm)
428 428
   {
429  
-    snd_pcm_drop (m_pcm);
430 429
     snd_pcm_close(m_pcm);
431 430
     m_pcm = NULL;
432 431
   }
@@ -487,7 +486,13 @@ double CAESinkALSA::GetCacheTotal()
487 486
 unsigned int CAESinkALSA::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio)
488 487
 {
489 488
   if (!m_pcm)
490  
-    return 0;
  489
+  {
  490
+    SoftResume();
  491
+    if(!m_pcm)
  492
+      return 0;
  493
+
  494
+    CLog::Log(LOGDEBUG, "CAESinkALSA - the grAEken is hunger, feed it (I am the downmost fallback - fix your code)");
  495
+  }
491 496
 
492 497
   int ret;
493 498
 
@@ -676,12 +681,17 @@ bool CAESinkALSA::OpenPCMDevice(const std::string &name, const std::string &para
676 681
   return false;
677 682
 }
678 683
 
679  
-void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list)
  684
+void CAESinkALSA::EnumerateDevicesEx(AEDeviceInfoList &list, bool force)
680 685
 {
681 686
   /* ensure that ALSA has been initialized */
682 687
   snd_lib_error_set_handler(sndLibErrorHandler);
683  
-  if(!snd_config)
  688
+  if(!snd_config || force)
  689
+  {
  690
+    if(force)
  691
+      snd_config_update_free_global();
  692
+
684 693
     snd_config_update();
  694
+  }
685 695
 
686 696
   snd_config_t *config;
687 697
   snd_config_copy(&config, snd_config);
@@ -1125,6 +1135,27 @@ bool CAESinkALSA::GetELD(snd_hctl_t *hctl, int device, CAEDeviceInfo& info, bool
1125 1135
   return true;
1126 1136
 }
1127 1137
 
  1138
+bool CAESinkALSA::SoftSuspend()
  1139
+{
  1140
+  if(m_pcm) // it is still there
  1141
+   Deinitialize();
  1142
+
  1143
+  return true;
  1144
+}
  1145
+bool CAESinkALSA::SoftResume()
  1146
+{
  1147
+	// reinit all the clibber
  1148
+    if(!m_pcm)
  1149
+    {
  1150
+      if (!snd_config)
  1151
+	    snd_config_update();
  1152
+
  1153
+      Initialize(m_initFormat, m_initDevice);
  1154
+    }
  1155
+   //we want that AE loves us again
  1156
+   return false; // force reinit
  1157
+}
  1158
+
1128 1159
 void CAESinkALSA::sndLibErrorHandler(const char *file, int line, const char *function, int err, const char *fmt, ...)
1129 1160
 {
1130 1161
   va_list arg;
4  xbmc/cores/AudioEngine/Sinks/AESinkALSA.h
@@ -49,8 +49,10 @@ class CAESinkALSA : public IAESink
49 49
   virtual double       GetCacheTotal   ();
50 50
   virtual unsigned int AddPackets      (uint8_t *data, unsigned int frames, bool hasAudio);
51 51
   virtual void         Drain           ();
  52
+  virtual bool         SoftSuspend();
  53
+  virtual bool         SoftResume();
52 54
 
53  
-  static void EnumerateDevicesEx(AEDeviceInfoList &list);
  55
+  static void EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false);
54 56
 private:
55 57
   CAEChannelInfo GetChannelLayout(AEAudioFormat format);
56 58
   void           GetAESParams(const AEAudioFormat format, std::string& params);
2  xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.cpp
@@ -236,7 +236,7 @@ void  CAESinkAUDIOTRACK::SetVolume(float scale)
236 236
   m_volume_changed = true;
237 237
 }
238 238
 
239  
-void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list)
  239
+void CAESinkAUDIOTRACK::EnumerateDevicesEx(AEDeviceInfoList &list, bool force)
240 240
 {
241 241
   m_info.m_channels.Reset();
242 242
   m_info.m_dataFormats.clear();
2  xbmc/cores/AudioEngine/Sinks/AESinkAUDIOTRACK.h
@@ -43,7 +43,7 @@ class CAESinkAUDIOTRACK : public CThread, public IAESink
43 43
   virtual void         Drain           ();
44 44
   virtual bool         HasVolume       ();
45 45
   virtual void         SetVolume       (float scale);
46  
-  static void          EnumerateDevicesEx(AEDeviceInfoList &list);
  46
+  static void          EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false);
47 47
 
48 48
 private:
49 49
   virtual void Process();
2  xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.cpp
@@ -464,7 +464,7 @@ double CAESinkDirectSound::GetCacheTotal()
464 464
   return (double)m_dwBufferLen / (double)m_AvgBytesPerSec;
465 465
 }
466 466
 
467  
-void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList)
  467
+void CAESinkDirectSound::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force)
468 468
 {
469 469
   CAEDeviceInfo        deviceInfo;
470 470
 
2  xbmc/cores/AudioEngine/Sinks/AESinkDirectSound.h
@@ -43,8 +43,8 @@ class CAESinkDirectSound : 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  
-  static  void         EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList);
47 46
   static  std::string  GetDefaultDevice   ();
  47
+  static  void         EnumerateDevicesEx (AEDeviceInfoList &deviceInfoList, bool force = false);
48 48
 private:
49 49
   void          AEChannelsFromSpeakerMask(DWORD speakers);
50 50
   DWORD         SpeakerMaskFromAEChannels(const CAEChannelInfo &channels);
2  xbmc/cores/AudioEngine/Sinks/AESinkOSS.cpp
@@ -427,7 +427,7 @@ void CAESinkOSS::Drain()
427 427
   // ???
428 428
 }
429 429
 
430  
-void CAESinkOSS::EnumerateDevicesEx(AEDeviceInfoList &list)
  430
+void CAESinkOSS::EnumerateDevicesEx(AEDeviceInfoList &list, bool force)
431 431
 {
432 432
   int mixerfd;
433 433
   const char * mixerdev = "/dev/mixer";
2  xbmc/cores/AudioEngine/Sinks/AESinkOSS.h
@@ -43,7 +43,7 @@ class CAESinkOSS : public IAESink
43 43
   virtual double       GetCacheTotal   () { return 0.0; } /* FIXME */
44 44
   virtual unsigned int AddPackets      (uint8_t *data, unsigned int frames, bool hasAudio);
45 45
   virtual void         Drain           ();
46  
-  static  void         EnumerateDevicesEx(AEDeviceInfoList &list);
  46
+  static  void         EnumerateDevicesEx(AEDeviceInfoList &list, bool force = false);
47 47
 private:
48 48
   int m_fd;
49 49
   std::string      m_device;
2  xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.cpp
@@ -559,7 +559,7 @@ bool CAESinkWASAPI::SoftResume()
559 559
   return false;
560 560
 }
561 561
 
562  
-void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList)
  562
+void CAESinkWASAPI::EnumerateDevicesEx(AEDeviceInfoList &deviceInfoList, bool force)
563 563
 {
564 564
   IMMDeviceEnumerator* pEnumerator = NULL;
565 565
   IMMDeviceCollection* pEnumDevices = NULL;
4  xbmc/cores/AudioEngine/Sinks/AESinkWASAPI.h
@@ -45,7 +45,7 @@ class CAESinkWASAPI : public IAESink
45 45
     virtual unsigned int AddPackets                  (uint8_t *data, unsigned int frames, bool hasAudio);
46 46
     virtual bool         SoftSuspend                 ();
47 47
     virtual bool         SoftResume                  ();
48  
-    static  void         EnumerateDevicesEx          (AEDeviceInfoList &deviceInfoList);
  48
+    static  void         EnumerateDevicesEx          (AEDeviceInfoList &deviceInfoList, bool force = false);
49 49
 private:
50 50
     bool         InitializeExclusive(AEAudioFormat &format);
51 51
     void         AEChannelsFromSpeakerMask(DWORD speakers);
@@ -78,4 +78,4 @@ class CAESinkWASAPI : public IAESink
78 78
     unsigned int        m_uiBufferLen;    /* wasapi endpoint buffer size, in frames */
79 79
     double              m_avgTimeWaiting; /* time between next buffer of data from SoftAE and driver call for data */
80 80
     double              m_sinkLatency;    /* time in seconds of total duration of the two WASAPI buffers */
81  
-};
  81
+};

0 notes on commit 3cfc1c8

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