Advertisement
Leopold

xbmc-10.1-Dharma-500-add_dual_audio_support-0.1.patch

Nov 8th, 2011
354
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 123.82 KB | None | 0 0
  1. diff -Naur xbmc-10.1-Dharma/guilib/AudioContext.cpp xbmc-10.1-Dharma.patch/guilib/AudioContext.cpp
  2. --- xbmc-10.1-Dharma/guilib/AudioContext.cpp    2011-10-31 13:42:18.549488208 +0000
  3. +++ xbmc-10.1-Dharma.patch/guilib/AudioContext.cpp  2011-10-31 13:41:01.644826659 +0000
  4. @@ -32,6 +32,7 @@
  5.  
  6.  
  7.  CAudioContext& g_audioContext = g_SystemGlobals.m_audioContext;
  8. +CAudioContext& g_audioContext2 = g_SystemGlobals.m_audioContext2;
  9.  
  10.  #ifdef _WIN32
  11.  static GUID g_digitaldevice;
  12. @@ -62,6 +63,21 @@
  13.  #endif
  14.    m_pDirectSoundDevice=NULL;
  15.  #endif
  16. +  m_bAudio2 = false;
  17. +}
  18. +
  19. +CAudioContext::CAudioContext(bool bAudio2)
  20. +{
  21. +  m_bAC3EncoderActive=false;
  22. +  m_iDevice=DEFAULT_DEVICE;
  23. +  m_strDevice.clear();
  24. +#ifdef HAS_AUDIO
  25. +#ifdef HAS_AUDIO_PASS_THROUGH
  26. +  m_pAC97Device=NULL;
  27. +#endif
  28. +  m_pDirectSoundDevice=NULL;
  29. +#endif
  30. +  m_bAudio2 = bAudio2;
  31.  }
  32.  
  33.  CAudioContext::~CAudioContext()
  34. @@ -71,7 +87,15 @@
  35.  // \brief Create a new device by type (DEFAULT_DEVICE, DIRECTSOUND_DEVICE, AC97_DEVICE)
  36.  void CAudioContext::SetActiveDevice(int iDevice)
  37.  {
  38. -  CStdString strAudioDev = g_guiSettings.GetString("audiooutput.audiodevice");
  39. +  CStdString strAudioDev;
  40. +  if(!m_bAudio2)
  41. +  {
  42. +    strAudioDev = g_guiSettings.GetString("audiooutput.audiodevice");
  43. +  }
  44. +  else
  45. +  {
  46. +    strAudioDev = g_guiSettings.GetString("audiooutput2.audiodevice");
  47. +  }
  48.  
  49.    /* if device is the same, no need to bother */
  50.  #ifdef _WIN32
  51. @@ -185,7 +209,10 @@
  52.      return;
  53.    }
  54.  #endif
  55. -  g_audioManager.Initialize(m_iDevice);
  56. +  if (!m_bAudio2)
  57. +  {
  58. +    g_audioManager.Initialize(m_iDevice);
  59. +  }
  60.  }
  61.  
  62.  // \brief Return the active device type (NONE, DEFAULT_DEVICE, DIRECTSOUND_DEVICE, AC97_DEVICE)
  63. @@ -198,7 +225,10 @@
  64.  void CAudioContext::RemoveActiveDevice()
  65.  {
  66.    CLog::Log(LOGDEBUG, "%s - Removing device %i", __FUNCTION__, m_iDevice);
  67. -  g_audioManager.DeInitialize(m_iDevice);
  68. +  if (!m_bAudio2)
  69. +  {
  70. +    g_audioManager.DeInitialize(m_iDevice);
  71. +  }
  72.    m_iDevice=NONE;
  73.  
  74.  #ifdef HAS_AUDIO
  75. @@ -218,7 +248,16 @@
  76.  #ifdef HAS_AUDIO
  77.    return; //not implemented
  78.    DWORD spconfig = DSSPEAKER_USE_DEFAULT;
  79. -  if (AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput.mode")))
  80. +  bool bBitStream;
  81. +  if (!m_bAudio2)
  82. +  {
  83. +    bBitStream = AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput.mode"));
  84. +  }
  85. +  else
  86. +  {
  87. +    bBitStream = AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput2.mode"));
  88. +  }
  89. +  if (bBitStream)
  90.    {
  91.      if (g_settings.m_currentVideoSettings.m_OutputToAllSpeakers && !bIsMusic)
  92.      {
  93. diff -Naur xbmc-10.1-Dharma/guilib/AudioContext.h xbmc-10.1-Dharma.patch/guilib/AudioContext.h
  94. --- xbmc-10.1-Dharma/guilib/AudioContext.h  2011-10-31 13:42:18.550488282 +0000
  95. +++ xbmc-10.1-Dharma.patch/guilib/AudioContext.h    2011-10-31 13:41:07.070226073 +0000
  96. @@ -41,6 +41,7 @@
  97.  {
  98.  public:
  99.    CAudioContext();
  100. +  CAudioContext(bool bAudio2);
  101.    virtual ~CAudioContext();
  102.  
  103.    void                        SetActiveDevice(int iDevice);
  104. @@ -71,6 +72,9 @@
  105.    int                          m_iDevice;
  106.    CStdString                   m_strDevice;
  107.    bool                         m_bAC3EncoderActive;
  108. +
  109. +  bool                         m_bAudio2;
  110.  };
  111.  
  112.  extern CAudioContext& g_audioContext;
  113. +extern CAudioContext& g_audioContext2;
  114. diff -Naur xbmc-10.1-Dharma/guilib/GUIBaseContainer.cpp xbmc-10.1-Dharma.patch/guilib/GUIBaseContainer.cpp
  115. --- xbmc-10.1-Dharma/guilib/GUIBaseContainer.cpp    2011-10-31 13:42:18.565489386 +0000
  116. +++ xbmc-10.1-Dharma.patch/guilib/GUIBaseContainer.cpp  2011-10-31 13:41:01.673828795 +0000
  117. @@ -810,8 +810,8 @@
  118.      CGUIListItemPtr item = m_items[i];
  119.      // The letter offset jumping is only for ASCII characters at present, and
  120.      // our checks are all done in uppercase
  121. -    CStdString nextLetter = item->GetSortLabel().Left(1);
  122. -    nextLetter.ToUpper();
  123. +    CStdString nextLetter;
  124. +    g_charsetConverter.wToUTF8(item->GetSortLabel().Left(1).ToUpper(), nextLetter);
  125.      if (currentMatch != nextLetter)
  126.      {
  127.        currentMatch = nextLetter;
  128. diff -Naur xbmc-10.1-Dharma/guilib/GUIListItem.cpp xbmc-10.1-Dharma.patch/guilib/GUIListItem.cpp
  129. --- xbmc-10.1-Dharma/guilib/GUIListItem.cpp 2011-10-31 13:42:18.626493879 +0000
  130. +++ xbmc-10.1-Dharma.patch/guilib/GUIListItem.cpp   2011-10-31 13:41:01.705831151 +0000
  131. @@ -22,6 +22,8 @@
  132.  #include "GUIListItem.h"
  133.  #include "GUIListItemLayout.h"
  134.  #include "utils/Archive.h"
  135. +#include "utils/CharsetConverter.h"
  136. +#include "utils/Variant.h"
  137.  
  138.  CGUIListItem::CGUIListItem(const CGUIListItem& item)
  139.  {
  140. @@ -49,7 +51,7 @@
  141.    m_bIsFolder = false;
  142.    m_strLabel2 = "";
  143.    m_strLabel = strLabel;
  144. -  m_sortLabel = strLabel;
  145. +  SetSortLabel(strLabel);
  146.    m_bSelected = false;
  147.    m_strIcon = "";
  148.    m_strThumbnailImage = "";
  149. @@ -69,7 +71,7 @@
  150.      return;
  151.    m_strLabel = strLabel;
  152.    if (m_sortLabel.IsEmpty())
  153. -    m_sortLabel = strLabel;
  154. +    SetSortLabel(strLabel);
  155.    SetInvalid();
  156.  }
  157.  
  158. @@ -94,11 +96,11 @@
  159.  
  160.  void CGUIListItem::SetSortLabel(const CStdString &label)
  161.  {
  162. -  m_sortLabel = label;
  163. +  g_charsetConverter.utf8ToW(label, m_sortLabel);
  164.    // no need to invalidate - this is never shown in the UI
  165.  }
  166.  
  167. -const CStdString& CGUIListItem::GetSortLabel() const
  168. +const CStdStringW& CGUIListItem::GetSortLabel() const
  169.  {
  170.    return m_sortLabel;
  171.  }
  172. diff -Naur xbmc-10.1-Dharma/guilib/GUIListItem.h xbmc-10.1-Dharma.patch/guilib/GUIListItem.h
  173. --- xbmc-10.1-Dharma/guilib/GUIListItem.h   2011-10-31 13:42:18.628494026 +0000
  174. +++ xbmc-10.1-Dharma.patch/guilib/GUIListItem.h 2011-10-31 13:41:07.096227986 +0000
  175. @@ -79,7 +79,7 @@
  176.    CStdString GetOverlayImage() const;
  177.  
  178.    void SetSortLabel(const CStdString &label);
  179. -  const CStdString &GetSortLabel() const;
  180. +  const CStdStringW &GetSortLabel() const;
  181.  
  182.    void Select(bool bOnOff);
  183.    bool IsSelected() const;
  184. @@ -144,7 +144,7 @@
  185.    typedef std::map<CStdString, CStdString, icompare> PropertyMap;
  186.    PropertyMap m_mapProperties;
  187.  private:
  188. -  CStdString m_sortLabel;     // text for sorting
  189. +  CStdStringW m_sortLabel;    // text for sorting. Need to be UTF16 for proper sorting
  190.    CStdString m_strLabel;      // text of column1
  191.  };
  192.  #endif
  193. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/ALSADirectSound.cpp xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/ALSADirectSound.cpp
  194. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/ALSADirectSound.cpp  2011-10-31 13:42:26.502073648 +0000
  195. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/ALSADirectSound.cpp    2011-10-31 13:41:00.737759883 +0000
  196. @@ -42,6 +42,14 @@
  197.    m_bIsAllocated = false;
  198.  }
  199.  
  200. +CALSADirectSound::CALSADirectSound(bool bAudio2)
  201. +{
  202. +  m_pPlayHandle  = NULL;
  203. +  m_bIsAllocated = false;
  204. +  m_bAudio2 = bAudio2;
  205. +  m_remap.SetAudio2(bAudio2);
  206. +}
  207. +
  208.  bool CALSADirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic, bool bPassthrough)
  209.  {
  210.    enum PCMChannels *outLayout;
  211. @@ -88,8 +96,16 @@
  212.    }
  213.  
  214.    bool bAudioOnAllSpeakers(false);
  215. -  g_audioContext.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
  216. -  g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  217. +  if (!m_bAudio2)
  218. +  {
  219. +    g_audioContext.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
  220. +    g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  221. +  }
  222. +  else
  223. +  {
  224. +    g_audioContext2.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
  225. +    g_audioContext2.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  226. +  }
  227.  
  228.    m_pPlayHandle = NULL;
  229.    m_bPause = false;
  230. @@ -314,7 +330,10 @@
  231.    }
  232.  
  233.    m_pPlayHandle=NULL;
  234. -  g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  235. +  if (!m_bAudio2)
  236. +    g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  237. +  else
  238. +    g_audioContext2.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  239.    return true;
  240.  }
  241.  
  242. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/ALSADirectSound.h xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/ALSADirectSound.h
  243. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/ALSADirectSound.h    2011-10-31 13:42:26.503073721 +0000
  244. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/ALSADirectSound.h  2011-10-31 13:41:06.600191469 +0000
  245. @@ -51,6 +51,7 @@
  246.    virtual float GetCacheTime();
  247.    virtual float GetCacheTotal();
  248.    CALSADirectSound();
  249. +  CALSADirectSound(bool bAudio2);
  250.    virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic=false, bool bPassthrough = false);
  251.    virtual ~CALSADirectSound();
  252.  
  253. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/AudioRendererFactory.cpp xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/AudioRendererFactory.cpp
  254. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/AudioRendererFactory.cpp 2011-10-31 13:42:26.504073794 +0000
  255. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/AudioRendererFactory.cpp   2011-10-31 13:41:00.760761577 +0000
  256. @@ -70,45 +70,68 @@
  257.    }                                        \
  258.  }
  259.  
  260. -#define CreateAndReturnOnValidInitialize(rendererClass) \
  261. +#define CreateAndReturnOnValidInitialize(rendererClass, bAudio2) \
  262.  { \
  263. -  audioSink = new rendererClass(); \
  264. +  audioSink = new rendererClass(bAudio2); \
  265.    ReturnOnValidInitialize(#rendererClass); \
  266.  }
  267.  
  268. -#define ReturnNewRenderer(rendererClass) \
  269. +#define ReturnNewRenderer(rendererClass, bAudio2) \
  270.  { \
  271.    renderer = #rendererClass; \
  272. -  return new rendererClass(); \
  273. +  return new rendererClass(bAudio2); \
  274.  }
  275.  
  276. -IAudioRenderer* CAudioRendererFactory::Create(IAudioCallback* pCallback, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic, bool bPassthrough)
  277. +IAudioRenderer* CAudioRendererFactory::Create(IAudioCallback* pCallback, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic, bool bPassthrough, bool bAudio2)
  278.  {
  279.    IAudioRenderer* audioSink = NULL;
  280.    CStdString renderer;
  281.  
  282.    CStdString deviceString, device;
  283. -  if (bPassthrough)
  284. +  if (!bAudio2)
  285.    {
  286. -#if defined(_LINUX) && !defined(__APPLE__)
  287. -    deviceString = g_guiSettings.GetString("audiooutput.passthroughdevice");
  288. -    if (deviceString.Equals("custom"))
  289. -      deviceString = g_guiSettings.GetString("audiooutput.custompassthrough");
  290. -#else
  291. -    // osx/win platforms do not have an "audiooutput.passthroughdevice" setting but can do passthrough
  292. -    deviceString = g_guiSettings.GetString("audiooutput.audiodevice");
  293. -#endif
  294. +    if (bPassthrough)
  295. +    {
  296. +  #if defined(_LINUX) && !defined(__APPLE__)
  297. +      deviceString = g_guiSettings.GetString("audiooutput.passthroughdevice");
  298. +      if (deviceString.Equals("custom"))
  299. +        deviceString = g_guiSettings.GetString("audiooutput.custompassthrough");
  300. +  #else
  301. +      // osx/win platforms do not have an "audiooutput.passthroughdevice" setting but can do passthrough
  302. +      deviceString = g_guiSettings.GetString("audiooutput.audiodevice");
  303. +  #endif
  304. +    }
  305. +    else
  306. +    {
  307. +      deviceString = g_guiSettings.GetString("audiooutput.audiodevice");
  308. +      if (deviceString.Equals("custom"))
  309. +        deviceString = g_guiSettings.GetString("audiooutput.customdevice");
  310. +    }
  311.    }
  312.    else
  313.    {
  314. -    deviceString = g_guiSettings.GetString("audiooutput.audiodevice");
  315. -    if (deviceString.Equals("custom"))
  316. -      deviceString = g_guiSettings.GetString("audiooutput.customdevice");
  317. +    if (bPassthrough)
  318. +    {
  319. +#if defined(_LINUX) && !defined(__APPLE__)
  320. +      deviceString = g_guiSettings.GetString("audiooutput2.passthroughdevice");
  321. +      if (deviceString.Equals("custom"))
  322. +        deviceString = g_guiSettings.GetString("audiooutput2.custompassthrough");
  323. +#else
  324. +      // osx/win platforms do not have an "audiooutput.passthroughdevice" setting but can do passthrough
  325. +      deviceString = g_guiSettings.GetString("audiooutput2.audiodevice");
  326. +#endif
  327. +    }
  328. +    else
  329. +    {
  330. +      deviceString = g_guiSettings.GetString("audiooutput2.audiodevice");
  331. +      if (deviceString.Equals("custom"))
  332. +        deviceString = g_guiSettings.GetString("audiooutput2.customdevice");
  333. +    }
  334.    }
  335.    int iPos = deviceString.Find(":");
  336.    if (iPos > 0)
  337.    {
  338. -    audioSink = CreateFromUri(deviceString.Left(iPos), renderer);
  339. +    audioSink = CreateFromUri(deviceString.Left(iPos), renderer, bAudio2);
  340.      if (audioSink)
  341.      {
  342.        device = deviceString.Right(deviceString.length() - iPos - 1);
  343. @@ -118,12 +141,12 @@
  344.        //If WASAPI failed try DirectSound.
  345.        if(deviceString.Left(iPos).Equals("wasapi"))
  346.        {
  347. -        audioSink = CreateFromUri("directsound", renderer);
  348. +        audioSink = CreateFromUri("directsound", renderer, bAudio2);
  349.          ReturnOnValidInitialize(renderer.c_str());
  350.        }
  351.  #endif
  352.  
  353. -      CreateAndReturnOnValidInitialize(CNullDirectSound);
  354. +      CreateAndReturnOnValidInitialize(CNullDirectSound, bAudio2);
  355.        /* should never get here */
  356.        assert(false);
  357.      }
  358. @@ -134,20 +157,20 @@
  359.  
  360.  /* First pass creation */
  361.  #ifdef HAS_PULSEAUDIO
  362. -  CreateAndReturnOnValidInitialize(CPulseAudioDirectSound);
  363. +  CreateAndReturnOnValidInitialize(CPulseAudioDirectSound, bAudio2);
  364.  #endif
  365.  
  366.  /* incase none in the first pass was able to be created, fall back to os specific */
  367.  #ifdef WIN32
  368. -  CreateAndReturnOnValidInitialize(CWin32DirectSound);
  369. +  CreateAndReturnOnValidInitialize(CWin32DirectSound, bAudio2);
  370.  #endif
  371.  #ifdef __APPLE__
  372. -  CreateAndReturnOnValidInitialize(CCoreAudioRenderer);
  373. +  CreateAndReturnOnValidInitialize(CCoreAudioRenderer, bAudio2);
  374.  #elif defined(_LINUX)
  375. -  CreateAndReturnOnValidInitialize(CALSADirectSound);
  376. +  CreateAndReturnOnValidInitialize(CALSADirectSound, bAudio2);
  377.  #endif
  378.  
  379. -  CreateAndReturnOnValidInitialize(CNullDirectSound);
  380. +  CreateAndReturnOnValidInitialize(CNullDirectSound, bAudio2);
  381.    /* should never get here */
  382.    assert(false);
  383.    return NULL;
  384. @@ -173,30 +196,30 @@
  385.  #endif
  386.  }
  387.  
  388. -IAudioRenderer *CAudioRendererFactory::CreateFromUri(const CStdString &soundsystem, CStdString &renderer)
  389. +IAudioRenderer *CAudioRendererFactory::CreateFromUri(const CStdString &soundsystem, CStdString &renderer, bool bAudio2)
  390.  {
  391.  #ifdef HAS_PULSEAUDIO
  392.    if (soundsystem.Equals("pulse"))
  393. -    ReturnNewRenderer(CPulseAudioDirectSound);
  394. +    ReturnNewRenderer(CPulseAudioDirectSound, bAudio2);
  395.  #endif
  396.  
  397.  #ifdef WIN32
  398.    if (soundsystem.Equals("wasapi"))
  399. -    ReturnNewRenderer(CWin32WASAPI)
  400. +    ReturnNewRenderer(CWin32WASAPI, bAudio2)
  401.    else if (soundsystem.Equals("directsound"))
  402. -    ReturnNewRenderer(CWin32DirectSound);
  403. +    ReturnNewRenderer(CWin32DirectSound, bAudio2);
  404.  #endif
  405.  
  406.  #ifdef __APPLE__
  407.    if (soundsystem.Equals("coreaudio"))
  408. -    ReturnNewRenderer(CCoreAudioRenderer);
  409. +    ReturnNewRenderer(CCoreAudioRenderer, bAudio2);
  410.  #elif defined(_LINUX)
  411.    if (soundsystem.Equals("alsa"))
  412. -    ReturnNewRenderer(CALSADirectSound);
  413. +    ReturnNewRenderer(CALSADirectSound, bAudio2);
  414.  #endif
  415.  
  416.    if (soundsystem.Equals("null"))
  417. -    ReturnNewRenderer(CNullDirectSound);
  418. +    ReturnNewRenderer(CNullDirectSound, bAudio2);
  419.  
  420.    return NULL;
  421.  }
  422. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/AudioRendererFactory.h xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/AudioRendererFactory.h
  423. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/AudioRendererFactory.h   2011-10-31 13:42:26.505073868 +0000
  424. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/AudioRendererFactory.h 2011-10-31 13:41:06.626193385 +0000
  425. @@ -31,9 +31,9 @@
  426.  class CAudioRendererFactory
  427.  {
  428.  public:
  429. -  static IAudioRenderer *Create(IAudioCallback* pCallback, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic, bool bPassthrough);
  430. +  static IAudioRenderer *Create(IAudioCallback* pCallback, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic, bool bPassthrough, bool bAudio2 = false);
  431.    static void EnumerateAudioSinks(AudioSinkList& vAudioSinks, bool passthrough);
  432.  private:
  433. -  static IAudioRenderer *CreateFromUri(const CStdString &soundsystem, CStdString &renderer);
  434. +  static IAudioRenderer *CreateFromUri(const CStdString &soundsystem, CStdString &renderer, bool bAudio2 = false);
  435.  };
  436.  #endif
  437. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/CoreAudioRenderer.cpp xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/CoreAudioRenderer.cpp
  438. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/CoreAudioRenderer.cpp    2011-10-31 13:42:26.506073943 +0000
  439. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/CoreAudioRenderer.cpp  2011-10-31 13:41:00.810765257 +0000
  440. @@ -344,6 +344,43 @@
  441.    }
  442.  }
  443.  
  444. +CCoreAudioRenderer::CCoreAudioRenderer(bool bAudio2) :
  445. +  m_Pause(false),
  446. +  m_ChunkLen(0),
  447. +  m_MaxCacheLen(0),
  448. +  m_AvgBytesPerSec(0),
  449. +  m_CurrentVolume(0),
  450. +  m_Initialized(false),
  451. +  m_Passthrough(false),
  452. +  m_EnableVolumeControl(true),
  453. +  m_OutputBufferIndex(0),
  454. +  m_pCache(NULL),
  455. +  m_RunoutEvent(kInvalidID),
  456. +  m_DoRunout(0)
  457. +{
  458. +  SInt32 major,  minor;
  459. +  Gestalt(gestaltSystemVersionMajor, &major);
  460. +  Gestalt(gestaltSystemVersionMinor, &minor);
  461. +
  462. +  // By default, kAudioHardwarePropertyRunLoop points at the process's main thread on SnowLeopard,
  463. +  // If your process lacks such a run loop, you can set kAudioHardwarePropertyRunLoop to NULL which
  464. +  // tells the HAL to run it's own thread for notifications (which was the default prior to SnowLeopard).
  465. +  // So tell the HAL to use its own thread for similar behavior under all supported versions of OSX.
  466. +  if (major == 10 && minor >=6)
  467. +  {
  468. +    CFRunLoopRef theRunLoop = NULL;
  469. +    AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyRunLoop, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster };
  470. +    OSStatus theError = AudioObjectSetPropertyData(kAudioObjectSystemObject, &theAddress, 0, NULL, sizeof(CFRunLoopRef), &theRunLoop);
  471. +    if (theError != noErr)
  472. +    {
  473. +      CLog::Log(LOGERROR, "CoreAudioRenderer::constructor: kAudioHardwarePropertyRunLoop error.");
  474. +    }
  475. +  }
  476. +
  477. +  m_bAudio2 = bAudio2;
  478. +  m_remap.SetAudio2(bAudio2);
  479. +}
  480. +
  481.  CCoreAudioRenderer::~CCoreAudioRenderer()
  482.  {
  483.    Deinitialize();
  484. @@ -363,15 +400,29 @@
  485.    if (m_Initialized) // Have to clean house before we start again. TODO: Should we return failure instead?
  486.      Deinitialize();
  487.  
  488. -  if(bPassthrough)
  489. -    g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE_DIGITAL);
  490. +  if (!m_bAudio2)
  491. +  {
  492. +    if(bPassthrough)
  493. +      g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE_DIGITAL);
  494. +    else
  495. +      g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  496. +  }
  497.    else
  498. -    g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  499. +  {
  500. +    if(bPassthrough)
  501. +      g_audioContext2.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE_DIGITAL);
  502. +    else
  503. +      g_audioContext2.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  504. +  }
  505.  
  506.    // TODO: If debugging, output information about all devices/streams
  507.  
  508.    // Attempt to find the configured output device
  509. -  AudioDeviceID outputDevice = CCoreAudioHardware::FindAudioDevice(g_guiSettings.GetString("audiooutput.audiodevice"));
  510. +  AudioDeviceID outputDevice;
  511. +  if (!m_bAudio2)
  512. +    outputDevice = CCoreAudioHardware::FindAudioDevice(g_guiSettings.GetString("audiooutput.audiodevice"));
  513. +  else
  514. +    outputDevice = CCoreAudioHardware::FindAudioDevice(g_guiSettings.GetString("audiooutput2.audiodevice"));
  515.    if (!outputDevice) // Fall back to the default device if no match is found
  516.    {
  517.      CLog::Log(LOGWARNING, "CoreAudioRenderer::Initialize: Unable to locate configured device, falling-back to the system default.");
  518. @@ -505,7 +556,10 @@
  519.    m_DoRunout = 0;
  520.    m_EnableVolumeControl = true;
  521.  
  522. -  g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  523. +  if (!m_bAudio2)
  524. +    g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  525. +  else
  526. +    g_audioContext2.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  527.  
  528.    CLog::Log(LOGINFO, "CoreAudioRenderer::Deinitialize: Renderer has been shut down.");
  529.  
  530. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/CoreAudioRenderer.h xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/CoreAudioRenderer.h
  531. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/CoreAudioRenderer.h  2011-10-31 13:42:26.508074091 +0000
  532. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/CoreAudioRenderer.h    2011-10-31 13:41:06.656195593 +0000
  533. @@ -102,6 +102,7 @@
  534.    {
  535.    public:
  536.      CCoreAudioRenderer();
  537. +    CCoreAudioRenderer(bool bAudio2);
  538.      virtual ~CCoreAudioRenderer();
  539.      virtual unsigned int GetChunkLen();
  540.      virtual float GetDelay();
  541. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/IAudioRenderer.h xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/IAudioRenderer.h
  542. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/IAudioRenderer.h 2011-10-31 13:42:26.509074164 +0000
  543. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/IAudioRenderer.h   2011-10-31 13:41:06.675196992 +0000
  544. @@ -41,7 +41,7 @@
  545.  class IAudioRenderer
  546.  {
  547.  public:
  548. -  IAudioRenderer() {};
  549. +  IAudioRenderer() { m_bAudio2= false; };
  550.    virtual ~IAudioRenderer() {};
  551.    virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic=false, bool bPassthrough = false) = 0;
  552.    virtual void UnRegisterAudioCallback() = 0;
  553. @@ -69,6 +69,7 @@
  554.  
  555.  protected:
  556.    CPCMRemap m_remap;
  557. +  bool m_bAudio2;
  558.  
  559.  private:
  560.  };
  561. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/NullDirectSound.cpp xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/NullDirectSound.cpp
  562. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/NullDirectSound.cpp  2011-10-31 13:42:26.512074384 +0000
  563. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/NullDirectSound.cpp    2011-10-31 13:41:00.832766876 +0000
  564. @@ -41,6 +41,11 @@
  565.  CNullDirectSound::CNullDirectSound()
  566.  {
  567.  }
  568. +CNullDirectSound::CNullDirectSound(bool bAudio2)
  569. +{
  570. +  m_bAudio2 = bAudio2;
  571. +  m_remap.SetAudio2(bAudio2);
  572. +}
  573.  bool CNullDirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic, bool bPassthrough)
  574.  {
  575.    CLog::Log(LOGERROR,"Creating a Null Audio Renderer, Check your audio settings as this should not happen");
  576. @@ -48,10 +53,21 @@
  577.      iChannels = 2;
  578.  
  579.    bool bAudioOnAllSpeakers(false);
  580. -  g_audioContext.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
  581. -  g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  582. +  if (!m_bAudio2)
  583. +  {
  584. +    g_audioContext.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
  585. +    g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  586. +
  587. +    g_application.m_guiDialogKaiToast.QueueNotification(CGUIDialogKaiToast::Error, "Failed to initialize audio device", "Check your audiosettings", TOAST_DISPLAY_TIME, false);
  588. +  }
  589. +  else
  590. +  {
  591. +    g_audioContext2.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
  592. +    g_audioContext2.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  593. +
  594. +    g_application.m_guiDialogKaiToast.QueueNotification(CGUIDialogKaiToast::Error, "Failed to initialize 2nd audio device", "Check your audiosettings", TOAST_DISPLAY_TIME, false);
  595. +  }
  596.  
  597. -  g_application.m_guiDialogKaiToast.QueueNotification(CGUIDialogKaiToast::Error, "Failed to initialize audio device", "Check your audiosettings", TOAST_DISPLAY_TIME, false);
  598.    m_timePerPacket = 1.0f / (float)(iChannels*(uiBitsPerSample/8) * uiSamplesPerSec);
  599.    m_packetsSent = 0;
  600.    m_paused = 0;
  601. @@ -69,7 +85,10 @@
  602.  //***********************************************************************************************
  603.  bool CNullDirectSound::Deinitialize()
  604.  {
  605. -  g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  606. +  if (!m_bAudio2)
  607. +    g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  608. +  else
  609. +    g_audioContext2.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  610.    return true;
  611.  }
  612.  
  613. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/NullDirectSound.h xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/NullDirectSound.h
  614. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/NullDirectSound.h    2011-10-31 13:42:26.513074458 +0000
  615. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/NullDirectSound.h  2011-10-31 13:41:06.690198097 +0000
  616. @@ -41,6 +41,7 @@
  617.    virtual float GetDelay();
  618.    virtual float GetCacheTime();
  619.    CNullDirectSound();
  620. +  CNullDirectSound(bool bAudio2);
  621.    virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic=false, bool bPassthrough = false);
  622.    virtual ~CNullDirectSound();
  623.  
  624. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/PulseAudioDirectSound.cpp xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/PulseAudioDirectSound.cpp
  625. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/PulseAudioDirectSound.cpp    2011-10-31 13:42:26.514074531 +0000
  626. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/PulseAudioDirectSound.cpp  2011-10-31 13:41:00.956776007 +0000
  627. @@ -144,6 +144,12 @@
  628.  {
  629.  }
  630.  
  631. +CPulseAudioDirectSound::CPulseAudioDirectSound(bool bAudio2)
  632. +{
  633. +  m_bAudio2 = bAudio2;
  634. +  m_remap.SetAudio2(bAudio2);
  635. +}
  636. +
  637.  bool CPulseAudioDirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels* channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic, bool bPassthrough)
  638.  {
  639.    m_remap.Reset();
  640. @@ -165,8 +171,16 @@
  641.    }
  642.  
  643.    bool bAudioOnAllSpeakers(false);
  644. -  g_audioContext.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
  645. -  g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  646. +  if (!m_bAudio2)
  647. +  {
  648. +    g_audioContext.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
  649. +    g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  650. +  }
  651. +  else
  652. +  {
  653. +    g_audioContext2.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
  654. +    g_audioContext2.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  655. +  }
  656.  
  657.    m_Context = NULL;
  658.    m_Stream = NULL;
  659. @@ -363,7 +377,10 @@
  660.      m_MainLoop = NULL;
  661.    }
  662.  
  663. -  g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  664. +  if (!m_bAudio2)
  665. +    g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  666. +  else
  667. +    g_audioContext2.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  668.    return true;
  669.  }
  670.  
  671. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/PulseAudioDirectSound.h xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/PulseAudioDirectSound.h
  672. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/PulseAudioDirectSound.h  2011-10-31 13:42:26.515074604 +0000
  673. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/PulseAudioDirectSound.h    2011-10-31 13:41:06.732201188 +0000
  674. @@ -47,6 +47,7 @@
  675.    virtual float GetCacheTime();
  676.    virtual float GetCacheTotal();
  677.    CPulseAudioDirectSound();
  678. +  CPulseAudioDirectSound(bool bAudio2);
  679.    virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic=false, bool bPassthrough = false);
  680.    virtual ~CPulseAudioDirectSound();
  681.  
  682. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/Win32DirectSound.cpp xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/Win32DirectSound.cpp
  683. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/Win32DirectSound.cpp 2011-10-31 13:42:26.517074752 +0000
  684. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/Win32DirectSound.cpp   2011-10-31 13:41:01.025781085 +0000
  685. @@ -80,6 +80,20 @@
  686.  {
  687.  }
  688.  
  689. +CWin32DirectSound::CWin32DirectSound(bool bAudio2) :
  690. +  m_Passthrough(false),
  691. +  m_AvgBytesPerSec(0),
  692. +  m_CacheLen(0),
  693. +  m_dwChunkSize(0),
  694. +  m_dwDataChunkSize(0),
  695. +  m_dwBufferLen(0),
  696. +  m_PreCacheSize(0),
  697. +  m_LastCacheCheck(0)
  698. +{
  699. +  m_bAudio2 = bAudio2;
  700. +  m_remap.SetAudio2(bAudio2);
  701. +}
  702. +
  703.  bool CWin32DirectSound::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels* channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic, bool bAudioPassthrough)
  704.  {
  705.    m_uiDataChannels = iChannels;
  706. @@ -99,12 +113,24 @@
  707.    }
  708.  
  709.    bool bAudioOnAllSpeakers(false);
  710. -  g_audioContext.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
  711. -  if(bAudioPassthrough)
  712. -    g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE_DIGITAL);
  713. +  if (!m_bAudio2)
  714. +  {
  715. +    g_audioContext.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
  716. +    if(bAudioPassthrough)
  717. +      g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE_DIGITAL);
  718. +    else
  719. +      g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  720. +    m_pDSound=g_audioContext.GetDirectSoundDevice();
  721. +  }
  722.    else
  723. -    g_audioContext.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  724. -  m_pDSound=g_audioContext.GetDirectSoundDevice();
  725. +  {
  726. +    g_audioContext2.SetupSpeakerConfig(iChannels, bAudioOnAllSpeakers, bIsMusic);
  727. +    if(bAudioPassthrough)
  728. +      g_audioContext2.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE_DIGITAL);
  729. +    else
  730. +      g_audioContext2.SetActiveDevice(CAudioContext::DIRECTSOUND_DEVICE);
  731. +    m_pDSound=g_audioContext2.GetDirectSoundDevice();
  732. +  }
  733.  
  734.    m_bPause = false;
  735.    m_bIsAllocated = false;
  736. @@ -243,7 +269,10 @@
  737.      m_dwChunkSize = 0;
  738.      m_dwBufferLen = 0;
  739.  
  740. -    g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  741. +    if (!m_bAudio2)
  742. +      g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  743. +    else
  744. +      g_audioContext2.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  745.    }
  746.    return true;
  747.  }
  748. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/Win32DirectSound.h xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/Win32DirectSound.h
  749. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/Win32DirectSound.h   2011-10-31 13:42:26.518074826 +0000
  750. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/Win32DirectSound.h 2011-10-31 13:41:06.755202882 +0000
  751. @@ -45,6 +45,7 @@
  752.    virtual float GetCacheTime();
  753.    virtual float GetCacheTotal();
  754.    CWin32DirectSound();
  755. +  CWin32DirectSound(bool bAudio2);
  756.    virtual bool Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels* channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic=false, bool bPassthrough = false);
  757.    virtual ~CWin32DirectSound();
  758.  
  759. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/Win32WASAPI.cpp xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/Win32WASAPI.cpp
  760. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/Win32WASAPI.cpp  2011-10-31 13:42:26.519074899 +0000
  761. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/Win32WASAPI.cpp    2011-10-31 13:41:01.061783738 +0000
  762. @@ -85,6 +85,23 @@
  763.    m_pDevice(NULL)
  764.  {
  765.  }
  766. +  
  767. +CWin32WASAPI::CWin32WASAPI(bool bAudio2) :
  768. +  m_bPassthrough(false),
  769. +  m_uiAvgBytesPerSec(0),
  770. +  m_CacheLen(0),
  771. +  m_uiChunkSize(0),
  772. +  m_uiSrcChunkSize(0),
  773. +  m_uiBufferLen(0),
  774. +  m_PreCacheSize(0),
  775. +  m_LastCacheCheck(0),
  776. +  m_pAudioClient(NULL),
  777. +  m_pRenderClient(NULL),
  778. +  m_pDevice(NULL)
  779. +{
  780. +  m_bAudio2 = bAudio2;
  781. +  m_remap.SetAudio2(bAudio2);
  782. +}
  783.  
  784.  bool CWin32WASAPI::Initialize(IAudioCallback* pCallback, const CStdString& device, int iChannels, enum PCMChannels *channelMap, unsigned int uiSamplesPerSec, unsigned int uiBitsPerSample, bool bResample, bool bIsMusic, bool bAudioPassthrough)
  785.  {
  786. @@ -180,7 +197,10 @@
  787.    IMMDeviceCollection* pEnumDevices = NULL;
  788.  
  789.    //Shut down Directsound.
  790. -  g_audioContext.SetActiveDevice(CAudioContext::NONE);
  791. +  if (!m_bAudio2)
  792. +    g_audioContext.SetActiveDevice(CAudioContext::NONE);
  793. +  else
  794. +    g_audioContext2.SetActiveDevice(CAudioContext::NONE);
  795.  
  796.    HRESULT hr = CoCreateInstance(CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL, IID_IMMDeviceEnumerator, (void**)&pEnumerator);
  797.    EXIT_ON_FAILURE(hr, __FUNCTION__": Could not allocate WASAPI device enumerator. CoCreateInstance error code: %i", hr)
  798. @@ -289,7 +309,10 @@
  799.    SAFE_RELEASE(m_pDevice);
  800.  
  801.    //Restart Directsound
  802. -  g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  803. +  if (!m_bAudio2)
  804. +    g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  805. +  else
  806. +    g_audioContext2.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  807.  
  808.    return false;
  809.  }
  810. @@ -320,7 +343,10 @@
  811.      m_bIsAllocated = false;
  812.  
  813.      //Restart Directsound for the interface sounds.
  814. -    g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  815. +    if (!m_bAudio2)
  816. +      g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  817. +    else
  818. +      g_audioContext2.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  819.    }
  820.    return true;
  821.  }
  822. diff -Naur xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/Win32WASAPI.h xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/Win32WASAPI.h
  823. --- xbmc-10.1-Dharma/xbmc/cores/AudioRenderers/Win32WASAPI.h    2011-10-31 13:42:26.521075046 +0000
  824. +++ xbmc-10.1-Dharma.patch/xbmc/cores/AudioRenderers/Win32WASAPI.h  2011-10-31 13:41:06.794205754 +0000
  825. @@ -40,6 +40,7 @@
  826.  {
  827.  public:
  828.    CWin32WASAPI();
  829. +  CWin32WASAPI(bool bAudio2);
  830.    virtual ~CWin32WASAPI();
  831.    virtual void UnRegisterAudioCallback();
  832.    virtual void RegisterAudioCallback(IAudioCallback* pCallback);
  833. diff -Naur xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDAudio.cpp xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDAudio.cpp
  834. --- xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDAudio.cpp  2011-10-31 13:42:30.176344133 +0000
  835. +++ xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDAudio.cpp    2011-10-31 13:41:01.087785651 +0000
  836. @@ -70,13 +70,13 @@
  837.    m_pCallback = NULL;
  838.  }
  839.  
  840. -bool CDVDAudio::Create(const DVDAudioFrame &audioframe, CodecID codec)
  841. +bool CDVDAudio::Create(const DVDAudioFrame &audioframe, CodecID codec, bool bAudio2/* = false*/)
  842.  {
  843.    CLog::Log(LOGNOTICE, "Creating audio device with codec id: %i, channels: %i, sample rate: %i, %s", codec, audioframe.channels, audioframe.sample_rate, audioframe.passthrough ? "pass-through" : "no pass-through");
  844.  
  845.    // if passthrough isset do something else
  846.    CSingleLock lock (m_critSection);
  847. -  m_pAudioDecoder = CAudioRendererFactory::Create(m_pCallback, audioframe.channels, audioframe.channel_map, audioframe.sample_rate, audioframe.bits_per_sample, false, false, audioframe.passthrough);
  848. +  m_pAudioDecoder = CAudioRendererFactory::Create(m_pCallback, audioframe.channels, audioframe.channel_map, audioframe.sample_rate, audioframe.bits_per_sample, false, false, audioframe.passthrough, bAudio2);
  849.  
  850.    if (!m_pAudioDecoder) return false;
  851.  
  852. diff -Naur xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDAudio.h xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDAudio.h
  853. --- xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDAudio.h    2011-10-31 13:42:30.177344206 +0000
  854. +++ xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDAudio.h  2011-10-31 13:41:06.810206932 +0000
  855. @@ -60,7 +60,7 @@
  856.    void SetDynamicRangeCompression(long drc);
  857.    void Pause();
  858.    void Resume();
  859. -  bool Create(const DVDAudioFrame &audioframe, CodecID codec);
  860. +  bool Create(const DVDAudioFrame &audioframe, CodecID codec, bool bAudio2 = false);
  861.    bool IsValidFormat(const DVDAudioFrame &audioframe);
  862.    void Destroy();
  863.    DWORD AddPackets(const DVDAudioFrame &audioframe);
  864. diff -Naur xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h
  865. --- xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h   2011-10-31 13:42:30.183344647 +0000
  866. +++ xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodec.h 2011-10-31 13:41:06.824207962 +0000
  867. @@ -55,7 +55,7 @@
  868.  {
  869.  public:
  870.  
  871. -  CDVDAudioCodec() {}
  872. +  CDVDAudioCodec() { m_bAudio2 = false; }
  873.    virtual ~CDVDAudioCodec() {}
  874.  
  875.    /*
  876. @@ -119,4 +119,10 @@
  877.     * should return amount of data decoded has buffered in preparation for next audio frame
  878.     */
  879.    virtual int GetBufferSize() { return 0; }
  880. +
  881. +  void SetAudio2(bool bAudio2){ m_bAudio2 = bAudio2; };
  882. +
  883. +protected:
  884. +
  885. +  bool m_bAudio2;
  886.  };
  887. diff -Naur xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp
  888. --- xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp  2011-10-31 13:42:30.196345606 +0000
  889. +++ xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthrough.cpp    2011-10-31 13:41:01.109787272 +0000
  890. @@ -176,13 +176,25 @@
  891.  {
  892.    bool bSupportsAC3Out = false;
  893.    bool bSupportsDTSOut = false;
  894. -  int audioMode = g_guiSettings.GetInt("audiooutput.mode");
  895. +  int audioMode;
  896. +  if (!m_bAudio2)
  897. +    audioMode = g_guiSettings.GetInt("audiooutput.mode");
  898. +  else
  899. +    audioMode = g_guiSettings.GetInt("audiooutput2.mode");
  900.  
  901.    // TODO - move this stuff somewhere else
  902.    if (AUDIO_IS_BITSTREAM(audioMode))
  903.    {
  904. -    bSupportsAC3Out = g_guiSettings.GetBool("audiooutput.ac3passthrough");
  905. -    bSupportsDTSOut = g_guiSettings.GetBool("audiooutput.dtspassthrough");
  906. +    if (!m_bAudio2)
  907. +    {
  908. +      bSupportsAC3Out = g_guiSettings.GetBool("audiooutput.ac3passthrough");
  909. +      bSupportsDTSOut = g_guiSettings.GetBool("audiooutput.dtspassthrough");
  910. +    }
  911. +    else
  912. +    {
  913. +      bSupportsAC3Out = g_guiSettings.GetBool("audiooutput2.ac3passthrough");
  914. +      bSupportsDTSOut = g_guiSettings.GetBool("audiooutput2.dtspassthrough");
  915. +    }
  916.    }
  917.  
  918.    //Samplerate cannot be checked here as we don't know it at this point in time.
  919. diff -Naur xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp
  920. --- xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp    2011-10-31 13:42:30.198345752 +0000
  921. +++ xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDCodecs/Audio/DVDAudioCodecPassthroughFFmpeg.cpp  2011-10-31 13:41:01.123788302 +0000
  922. @@ -309,6 +309,7 @@
  923.  
  924.    /* create and setup the encoder */
  925.    m_Encoder     = new CDVDAudioEncoderFFmpeg();
  926. +  m_Encoder->SetAudio2(m_bAudio2);
  927.    m_InitEncoder = true;
  928.  
  929.    /* adjust the hints according to the encorders output */
  930. @@ -322,17 +323,33 @@
  931.  
  932.  bool CDVDAudioCodecPassthroughFFmpeg::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
  933.  {
  934. -  int audioMode = g_guiSettings.GetInt("audiooutput.mode");
  935. +    int audioMode;
  936. +    if (!m_bAudio2)
  937. +      audioMode = g_guiSettings.GetInt("audiooutput.mode");
  938. +    else
  939. +      audioMode = g_guiSettings.GetInt("audiooutput2.mode");
  940.  
  941.    // TODO - move this stuff somewhere else
  942.    if (AUDIO_IS_BITSTREAM(audioMode))
  943.    {
  944. -    m_bSupportsAC3Out = g_guiSettings.GetBool("audiooutput.ac3passthrough");
  945. -    m_bSupportsDTSOut = g_guiSettings.GetBool("audiooutput.dtspassthrough");
  946. -    m_bSupportsAACOut = g_guiSettings.GetBool("audiooutput.passthroughaac");
  947. -    m_bSupportsMP1Out = g_guiSettings.GetBool("audiooutput.passthroughmp1");
  948. -    m_bSupportsMP2Out = g_guiSettings.GetBool("audiooutput.passthroughmp2");
  949. -    m_bSupportsMP3Out = g_guiSettings.GetBool("audiooutput.passthroughmp3");
  950. +    if (!m_bAudio2)
  951. +    {
  952. +      m_bSupportsAC3Out = g_guiSettings.GetBool("audiooutput.ac3passthrough");
  953. +      m_bSupportsDTSOut = g_guiSettings.GetBool("audiooutput.dtspassthrough");
  954. +      m_bSupportsAACOut = g_guiSettings.GetBool("audiooutput.passthroughaac");
  955. +      m_bSupportsMP1Out = g_guiSettings.GetBool("audiooutput.passthroughmp1");
  956. +      m_bSupportsMP2Out = g_guiSettings.GetBool("audiooutput.passthroughmp2");
  957. +      m_bSupportsMP3Out = g_guiSettings.GetBool("audiooutput.passthroughmp3");
  958. +    }
  959. +    else
  960. +    {
  961. +      m_bSupportsAC3Out = g_guiSettings.GetBool("audiooutput2.ac3passthrough");
  962. +      m_bSupportsDTSOut = g_guiSettings.GetBool("audiooutput2.dtspassthrough");
  963. +      m_bSupportsAACOut = g_guiSettings.GetBool("audiooutput2.passthroughaac");
  964. +      m_bSupportsMP1Out = g_guiSettings.GetBool("audiooutput2.passthroughmp1");
  965. +      m_bSupportsMP2Out = g_guiSettings.GetBool("audiooutput2.passthroughmp2");
  966. +      m_bSupportsMP3Out = g_guiSettings.GetBool("audiooutput2.passthroughmp3");
  967. +    }
  968.    }
  969.    else
  970.      return false;
  971. diff -Naur xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/DVDAudioEncoderFFmpeg.cpp xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/DVDAudioEncoderFFmpeg.cpp
  972. --- xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/DVDAudioEncoderFFmpeg.cpp    2011-10-31 13:42:30.207346414 +0000
  973. +++ xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/DVDAudioEncoderFFmpeg.cpp  2011-10-31 13:41:01.158790879 +0000
  974. @@ -91,6 +91,7 @@
  975.    if (m_CodecCtx->channel_layout & CH_TOP_BACK_CENTER      ) m_ChannelMap[index++] = PCM_TOP_BACK_CENTER      ;
  976.    if (m_CodecCtx->channel_layout & CH_TOP_BACK_RIGHT       ) m_ChannelMap[index++] = PCM_TOP_BACK_RIGHT       ;
  977.  
  978. +  m_Remap.SetAudio2(m_bAudio2);
  979.    m_Remap.SetInputFormat (channels, channelMap, bitsPerSample / 8);
  980.    m_Remap.SetOutputFormat(index, m_ChannelMap, true);
  981.  
  982. diff -Naur xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/IDVDAudioEncoder.h xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/IDVDAudioEncoder.h
  983. --- xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/IDVDAudioEncoder.h   2011-10-31 13:42:30.210346637 +0000
  984. +++ xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDCodecs/Audio/Encoders/IDVDAudioEncoder.h 2011-10-31 13:41:06.838208991 +0000
  985. @@ -26,7 +26,7 @@
  986.  class IDVDAudioEncoder
  987.  {
  988.  public:
  989. -  IDVDAudioEncoder() {};
  990. +  IDVDAudioEncoder() {m_bAudio2 = false;};
  991.    virtual ~IDVDAudioEncoder() {};
  992.    virtual bool Initialize(unsigned int channels, enum PCMChannels *channelMap, unsigned int bitsPerSample, unsigned int sampleRate) = 0;
  993.    virtual void Reset() = 0;
  994. @@ -39,5 +39,11 @@
  995.    /* add/get packets to/from the DSP */
  996.    virtual int Encode (uint8_t *data, int size) = 0;
  997.    virtual int GetData(uint8_t **data) = 0;
  998. +
  999. +  void SetAudio2(bool bAudio2){ m_bAudio2 = bAudio2; };
  1000. +
  1001. +protected:
  1002. +
  1003. +  bool m_bAudio2;
  1004.  };
  1005.  
  1006. diff -Naur xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp
  1007. --- xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp 2011-10-31 13:42:30.223347594 +0000
  1008. +++ xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp   2011-10-31 13:41:01.178792350 +0000
  1009. @@ -81,11 +81,12 @@
  1010.    return NULL;
  1011.  }
  1012.  
  1013. -CDVDAudioCodec* CDVDFactoryCodec::OpenCodec(CDVDAudioCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options )
  1014. +CDVDAudioCodec* CDVDFactoryCodec::OpenCodec(CDVDAudioCodec* pCodec, CDVDStreamInfo &hints, CDVDCodecOptions &options, bool bAudio2 /* = false */ )
  1015.  {
  1016.    try
  1017.    {
  1018.      CLog::Log(LOGDEBUG, "FactoryCodec - Audio: %s - Opening", pCodec->GetName());
  1019. +    pCodec->SetAudio2(bAudio2);
  1020.      if( pCodec->Open( hints, options ) )
  1021.      {
  1022.        CLog::Log(LOGDEBUG, "FactoryCodec - Audio: %s - Opened", pCodec->GetName());
  1023. @@ -234,7 +235,7 @@
  1024.    return NULL;
  1025.  }
  1026.  
  1027. -CDVDAudioCodec* CDVDFactoryCodec::CreateAudioCodec( CDVDStreamInfo &hint, bool passthrough /* = true */)
  1028. +CDVDAudioCodec* CDVDFactoryCodec::CreateAudioCodec( CDVDStreamInfo &hint, bool passthrough /* = true */, bool bAudio2 /* = false */)
  1029.  {
  1030.    CDVDAudioCodec* pCodec = NULL;
  1031.    CDVDCodecOptions options;
  1032. @@ -242,11 +243,11 @@
  1033.    if (passthrough)
  1034.    {
  1035.  #if (defined(USE_LIBA52_DECODER) || defined(USE_LIBDTS_DECODER)) && !defined(WIN32)
  1036. -    pCodec = OpenCodec( new CDVDAudioCodecPassthrough(), hint, options );
  1037. +    pCodec = OpenCodec( new CDVDAudioCodecPassthrough(), hint, options, bAudio2);
  1038.      if( pCodec ) return pCodec;
  1039.  #endif
  1040.  
  1041. -    pCodec = OpenCodec( new CDVDAudioCodecPassthroughFFmpeg(), hint, options);
  1042. +    pCodec = OpenCodec( new CDVDAudioCodecPassthroughFFmpeg(), hint, options, bAudio2);
  1043.      if ( pCodec ) return pCodec;
  1044.    }
  1045.  
  1046. @@ -255,7 +256,7 @@
  1047.  #ifdef USE_LIBA52_DECODER
  1048.    case CODEC_ID_AC3:
  1049.      {
  1050. -      pCodec = OpenCodec( new CDVDAudioCodecLiba52(), hint, options );
  1051. +      pCodec = OpenCodec( new CDVDAudioCodecLiba52(), hint, options, bAudio2 );
  1052.        if( pCodec ) return pCodec;
  1053.        break;
  1054.      }
  1055. @@ -263,7 +264,7 @@
  1056.  #ifdef USE_LIBDTS_DECODER
  1057.    case CODEC_ID_DTS:
  1058.      {
  1059. -      pCodec = OpenCodec( new CDVDAudioCodecLibDts(), hint, options );
  1060. +      pCodec = OpenCodec( new CDVDAudioCodecLibDts(), hint, options, bAudio2 );
  1061.        if( pCodec ) return pCodec;
  1062.        break;
  1063.      }
  1064. @@ -271,7 +272,7 @@
  1065.    case CODEC_ID_MP2:
  1066.    case CODEC_ID_MP3:
  1067.      {
  1068. -      pCodec = OpenCodec( new CDVDAudioCodecLibMad(), hint, options );
  1069. +      pCodec = OpenCodec( new CDVDAudioCodecLibMad(), hint, options, bAudio2 );
  1070.        if( pCodec ) return pCodec;
  1071.        break;
  1072.      }
  1073. @@ -279,7 +280,7 @@
  1074.    case CODEC_ID_AAC:
  1075.    //case CODEC_ID_MPEG4AAC:
  1076.      {
  1077. -      pCodec = OpenCodec( new CDVDAudioCodecLibFaad(), hint, options );
  1078. +      pCodec = OpenCodec( new CDVDAudioCodecLibFaad(), hint, options, bAudio2 );
  1079.        if( pCodec ) return pCodec;
  1080.        break;
  1081.      }
  1082. @@ -302,7 +303,7 @@
  1083.    case CODEC_ID_PCM_ALAW:
  1084.    case CODEC_ID_PCM_MULAW:
  1085.      {
  1086. -      pCodec = OpenCodec( new CDVDAudioCodecPcm(), hint, options );
  1087. +      pCodec = OpenCodec( new CDVDAudioCodecPcm(), hint, options, bAudio2 );
  1088.        if( pCodec ) return pCodec;
  1089.        break;
  1090.      }
  1091. @@ -323,7 +324,7 @@
  1092.      }
  1093.    }
  1094.  
  1095. -  pCodec = OpenCodec( new CDVDAudioCodecFFmpeg(), hint, options );
  1096. +  pCodec = OpenCodec( new CDVDAudioCodecFFmpeg(), hint, options, bAudio2 );
  1097.    if( pCodec ) return pCodec;
  1098.  
  1099.    return NULL;
  1100. diff -Naur xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h
  1101. --- xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h   2011-10-31 13:42:30.224347668 +0000
  1102. +++ xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.h 2011-10-31 13:41:06.854210171 +0000
  1103. @@ -36,10 +36,10 @@
  1104.  {
  1105.  public:
  1106.    static CDVDVideoCodec* CreateVideoCodec(CDVDStreamInfo &hint );
  1107. -  static CDVDAudioCodec* CreateAudioCodec(CDVDStreamInfo &hint, bool passthrough = true );
  1108. +  static CDVDAudioCodec* CreateAudioCodec(CDVDStreamInfo &hint, bool passthrough = true, bool bAudio2 = false);
  1109.    static CDVDOverlayCodec* CreateOverlayCodec(CDVDStreamInfo &hint );
  1110.  
  1111. -  static CDVDAudioCodec* OpenCodec(CDVDAudioCodec* pCodec, CDVDStreamInfo &hint, CDVDCodecOptions &options );
  1112. +  static CDVDAudioCodec* OpenCodec(CDVDAudioCodec* pCodec, CDVDStreamInfo &hint, CDVDCodecOptions &options, bool bAudio2 = false );
  1113.    static CDVDVideoCodec* OpenCodec(CDVDVideoCodec* pCodec, CDVDStreamInfo &hint, CDVDCodecOptions &options );
  1114.    static CDVDOverlayCodec* OpenCodec(CDVDOverlayCodec* pCodec, CDVDStreamInfo &hint, CDVDCodecOptions &options );
  1115.  };
  1116. diff -Naur xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.cpp xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.cpp
  1117. --- xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.cpp 2011-10-31 13:42:30.298353116 +0000
  1118. +++ xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.cpp   2011-10-31 13:41:01.205794338 +0000
  1119. @@ -95,3 +95,21 @@
  1120.    }
  1121.    return pPacket;
  1122.  }
  1123. +
  1124. +DemuxPacket* CDVDDemuxUtils::DuplicateDemuxPacket(DemuxPacket* pPacket)
  1125. +{
  1126. +  if (NULL ==pPacket || pPacket->iSize <= 0)
  1127. +    return NULL;
  1128. +  DemuxPacket* pPacketDup = AllocateDemuxPacket( pPacket->iSize );
  1129. +  if( pPacketDup )
  1130. +  {
  1131. +    memcpy(pPacketDup->pData, pPacket->pData, pPacket->iSize);
  1132. +    pPacketDup->iSize = pPacket->iSize;
  1133. +    pPacketDup->iStreamId = pPacket->iStreamId;
  1134. +    pPacketDup->iGroupId = pPacket->iGroupId;
  1135. +    pPacketDup->pts = pPacket->pts;
  1136. +    pPacketDup->dts = pPacket->dts;
  1137. +    pPacketDup->duration = pPacket->duration;
  1138. +  }
  1139. +  return pPacketDup;
  1140. +}
  1141. diff -Naur xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.h xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.h
  1142. --- xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.h   2011-10-31 13:42:30.299353189 +0000
  1143. +++ xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.h 2011-10-31 13:41:06.868211201 +0000
  1144. @@ -28,5 +28,6 @@
  1145.  public:
  1146.    static void FreeDemuxPacket(DemuxPacket* pPacket);
  1147.    static DemuxPacket* AllocateDemuxPacket(int iDataSize = 0);
  1148. +  static DemuxPacket* DuplicateDemuxPacket(DemuxPacket* pPacket);
  1149.  };
  1150.  
  1151. diff -Naur xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp
  1152. --- xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp    2011-10-31 13:42:31.630451177 +0000
  1153. +++ xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDPlayerAudio.cpp  2011-10-31 13:41:01.242797064 +0000
  1154. @@ -131,9 +131,14 @@
  1155.  , m_messageQueue("audio")
  1156.  , m_messageParent(parent)
  1157.  , m_dvdAudio((bool&)m_bStop)
  1158. +, m_dvdAudio2((bool&)m_bStop)
  1159.  {
  1160.    m_pClock = pClock;
  1161.    m_pAudioCodec = NULL;
  1162. +  m_pAudioCodec2 = NULL;
  1163. +  m_bAudio2 = false;
  1164. +  m_bAudio2Stuck = false;
  1165. +  m_bAudio2Pause = false;
  1166.    m_audioClock = 0;
  1167.    m_droptime = 0;
  1168.    m_speed = DVD_PLAYSPEED_NORMAL;
  1169. @@ -159,13 +164,17 @@
  1170.  
  1171.  bool CDVDPlayerAudio::OpenStream( CDVDStreamInfo &hints )
  1172.  {
  1173. +  bool bAudio2 = (g_guiSettings.GetInt("audiooutput2.mode") == AUDIO_NONE) ? false : true;
  1174. +
  1175.    // should alway's be NULL!!!!, it will probably crash anyway when deleting m_pAudioCodec here.
  1176. -  if (m_pAudioCodec)
  1177. +  if (m_pAudioCodec || (bAudio2 && m_pAudioCodec2))
  1178.    {
  1179.      CLog::Log(LOGFATAL, "CDVDPlayerAudio::OpenStream() m_pAudioCodec != NULL");
  1180.      return false;
  1181.    }
  1182.  
  1183. +  m_bAudio2 = bAudio2;
  1184. +
  1185.    /* try to open decoder without probing, we could actually allow us to continue here */
  1186.    if( !OpenDecoder(hints) ) return false;
  1187.  
  1188. @@ -217,9 +226,13 @@
  1189.    {
  1190.      m_bStop = false;
  1191.      m_dvdAudio.Drain();
  1192. +    if (m_bAudio2)
  1193. +      m_dvdAudio2.Drain();
  1194.      m_bStop = true;
  1195.    }
  1196.    m_dvdAudio.Destroy();
  1197. +  if (m_bAudio2)
  1198. +    m_dvdAudio2.Destroy();
  1199.  
  1200.    // uninit queue
  1201.    m_messageQueue.End();
  1202. @@ -231,6 +244,14 @@
  1203.      delete m_pAudioCodec;
  1204.      m_pAudioCodec = NULL;
  1205.    }
  1206. +  if (m_pAudioCodec2)
  1207. +  {
  1208. +    m_pAudioCodec2->Dispose();
  1209. +    delete m_pAudioCodec2;
  1210. +    m_pAudioCodec2 = NULL;
  1211. +  }
  1212. +
  1213. +  m_bAudio2 = false;
  1214.  
  1215.    // flush any remaining pts values
  1216.    m_ptsOutput.Flush();
  1217. @@ -246,10 +267,17 @@
  1218.      m_pAudioCodec->Dispose();
  1219.      SAFE_DELETE(m_pAudioCodec);
  1220.    }
  1221. +  if( m_pAudioCodec2 )
  1222. +  {
  1223. +    CLog::Log(LOGNOTICE, "Deleting 2nd audio codec");
  1224. +    m_pAudioCodec2->Dispose();
  1225. +    SAFE_DELETE(m_pAudioCodec2);
  1226. +  }
  1227.  
  1228.    /* store our stream hints */
  1229.    m_streaminfo = hints;
  1230.    bool passthrough = AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput.mode"));
  1231. +  bool passthrough2 = AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput2.mode"));
  1232.  
  1233.    CLog::Log(LOGNOTICE, "Finding audio codec for: %i", m_streaminfo.codec);
  1234.    m_pAudioCodec = CDVDFactoryCodec::CreateAudioCodec(m_streaminfo, passthrough);
  1235. @@ -260,6 +288,16 @@
  1236.      m_streaminfo.Clear();
  1237.      return false;
  1238.    }
  1239. +  if (m_bAudio2)
  1240. +  {
  1241. +    m_pAudioCodec2 = CDVDFactoryCodec::CreateAudioCodec(m_streaminfo, passthrough2, m_bAudio2);
  1242. +    if( !m_pAudioCodec2 )
  1243. +    {
  1244. +      CLog::Log(LOGERROR, "Unsupported 2nd audio codec");
  1245. +      m_dvdAudio2.Destroy();
  1246. +      m_bAudio2 = false;
  1247. +    }
  1248. +  }
  1249.  
  1250.    /* update codec information from what codec gave ut */
  1251.    m_streaminfo.channels = m_pAudioCodec->GetChannels();
  1252. @@ -269,19 +307,20 @@
  1253.  }
  1254.  
  1255.  // decode one audio frame and returns its uncompressed size
  1256. -int CDVDPlayerAudio::DecodeFrame(DVDAudioFrame &audioframe, bool bDropPacket)
  1257. +int CDVDPlayerAudio::DecodeFrame(DVDAudioFrame &audioframe, DVDAudioFrame &audioframe2, bool bDropPacket)
  1258.  {
  1259.    int result = 0;
  1260.  
  1261.    // make sure the sent frame is clean
  1262.    memset(&audioframe, 0, sizeof(DVDAudioFrame));
  1263. +  memset(&audioframe2, 0, sizeof(DVDAudioFrame));
  1264.  
  1265.    while (!m_bStop)
  1266.    {
  1267.      /* NOTE: the audio packet can contain several frames */
  1268.      while( !m_bStop && m_decode.size > 0 )
  1269.      {
  1270. -      if( !m_pAudioCodec )
  1271. +      if( !m_pAudioCodec || (m_bAudio2 && !m_pAudioCodec2) )
  1272.          return DECODE_FLAG_ERROR;
  1273.  
  1274.        /* the packet dts refers to the first audioframe that starts in the packet */
  1275. @@ -290,6 +329,8 @@
  1276.          m_audioClock = dts;
  1277.  
  1278.        int len = m_pAudioCodec->Decode(m_decode.data, m_decode.size);
  1279. +      if (m_bAudio2)
  1280. +        m_pAudioCodec2->Decode(m_decode.data, m_decode.size);
  1281.        m_audioStats.AddSampleBytes(m_decode.size);
  1282.        if (len < 0)
  1283.        {
  1284. @@ -297,6 +338,8 @@
  1285.          CLog::Log(LOGERROR, "CDVDPlayerAudio::DecodeFrame - Decode Error. Skipping audio packet");
  1286.          m_decode.Release();
  1287.          m_pAudioCodec->Reset();
  1288. +        if (m_bAudio2)
  1289. +          m_pAudioCodec2->Reset();
  1290.          return DECODE_FLAG_ERROR;
  1291.        }
  1292.  
  1293. @@ -306,6 +349,8 @@
  1294.          CLog::Log(LOGERROR, "CDVDPlayerAudio:DecodeFrame - Codec tried to consume more data than available. Potential memory corruption");
  1295.          m_decode.Release();
  1296.          m_pAudioCodec->Reset();
  1297. +        if (m_bAudio2)
  1298. +          m_pAudioCodec2->Reset();
  1299.          assert(0);
  1300.        }
  1301.  
  1302. @@ -322,6 +367,17 @@
  1303.        audioframe.sample_rate = m_pAudioCodec->GetSampleRate();
  1304.        audioframe.passthrough = m_pAudioCodec->NeedPassthrough();
  1305.  
  1306. +      if (m_bAudio2)
  1307. +      {
  1308. +        audioframe2.size = m_pAudioCodec2->GetData(&audioframe2.data);
  1309. +        audioframe2.pts = m_audioClock;
  1310. +        audioframe2.channel_map = m_pAudioCodec2->GetChannelMap();
  1311. +        audioframe2.channels = m_pAudioCodec2->GetChannels(); /* get channels AFTER map so that it can be corrected if bad */
  1312. +        audioframe2.bits_per_sample = m_pAudioCodec2->GetBitsPerSample();
  1313. +        audioframe2.sample_rate = m_pAudioCodec2->GetSampleRate();
  1314. +        audioframe2.passthrough = m_pAudioCodec2->NeedPassthrough();
  1315. +      }
  1316. +
  1317.        if (audioframe.size <= 0)
  1318.          continue;
  1319.  
  1320. @@ -335,6 +391,15 @@
  1321.          // increase audioclock to after the packet
  1322.          m_audioClock += audioframe.duration;
  1323.        }
  1324. +      if (m_bAudio2)
  1325. +      {
  1326. +        n = (audioframe2.channels * audioframe2.bits_per_sample * audioframe2.sample_rate)>>3;
  1327. +        if (n > 0)
  1328. +        {
  1329. +          // safety check, if channels == 0, n will result in 0, and that will result in a nice devide exception
  1330. +          audioframe2.duration = ((double)audioframe2.size * DVD_TIME_BASE) / n;
  1331. +        }
  1332. +      }
  1333.  
  1334.        if(audioframe.duration > 0)
  1335.          m_duration = audioframe.duration;
  1336. @@ -415,12 +480,16 @@
  1337.      {
  1338.        if (m_pAudioCodec)
  1339.          m_pAudioCodec->Reset();
  1340. +      if (m_pAudioCodec2)
  1341. +        m_pAudioCodec2->Reset();
  1342.        m_decode.Release();
  1343.        m_started = false;
  1344.      }
  1345.      else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH))
  1346.      {
  1347.        m_dvdAudio.Flush();
  1348. +      if (m_bAudio2)
  1349. +        m_dvdAudio2.Flush();
  1350.        m_ptsOutput.Flush();
  1351.        m_ptsInput.Flush();
  1352.        m_resampler.Flush();
  1353. @@ -430,6 +499,8 @@
  1354.  
  1355.        if (m_pAudioCodec)
  1356.          m_pAudioCodec->Reset();
  1357. +      if (m_pAudioCodec2)
  1358. +        m_pAudioCodec2->Reset();
  1359.  
  1360.        m_decode.Release();
  1361.      }
  1362. @@ -442,6 +513,8 @@
  1363.      {
  1364.        CLog::Log(LOGDEBUG, "CDVDPlayerAudio - CDVDMsg::GENERAL_EOF");
  1365.        m_dvdAudio.Finish();
  1366. +      if (m_bAudio2)
  1367. +        m_dvdAudio2.Finish();
  1368.      }
  1369.      else if (pMsg->IsType(CDVDMsg::GENERAL_DELAY))
  1370.      {
  1371. @@ -465,6 +538,8 @@
  1372.        if (m_speed == DVD_PLAYSPEED_NORMAL)
  1373.        {
  1374.          m_dvdAudio.Resume();
  1375. +        if (m_bAudio2)
  1376. +          m_dvdAudio2.Resume();
  1377.        }
  1378.        else
  1379.        {
  1380. @@ -472,8 +547,14 @@
  1381.          m_resampler.Flush();
  1382.          m_syncclock = true;
  1383.          if (m_speed != DVD_PLAYSPEED_PAUSE)
  1384. +        {
  1385.            m_dvdAudio.Flush();
  1386. +          if (m_bAudio2)
  1387. +            m_dvdAudio2.Flush();
  1388. +        }
  1389.          m_dvdAudio.Pause();
  1390. +        if (m_bAudio2)
  1391. +          m_dvdAudio2.Pause();
  1392.        }
  1393.      }
  1394.      pMsg->Release();
  1395. @@ -503,12 +584,16 @@
  1396.    bool packetadded(false);
  1397.  
  1398.    DVDAudioFrame audioframe;
  1399. +  DVDAudioFrame audioframe2;
  1400.    m_audioStats.Start();
  1401. +  m_audiodiff = 0.0;
  1402. +  m_bAudio2Stuck = false;
  1403. +  m_bAudio2Pause = false;
  1404.  
  1405.    while (!m_bStop)
  1406.    {
  1407.      //Don't let anybody mess with our global variables
  1408. -    result = DecodeFrame(audioframe, m_speed > DVD_PLAYSPEED_NORMAL || m_speed < 0); // blocks if no audio is available, but leaves critical section before doing so
  1409. +    result = DecodeFrame(audioframe, audioframe2, m_speed > DVD_PLAYSPEED_NORMAL || m_speed < 0); // blocks if no audio is available, but leaves critical section before doing so
  1410.  
  1411.      if( result & DECODE_FLAG_ERROR )
  1412.      {
  1413. @@ -522,7 +607,11 @@
  1414.  
  1415.        // Flush as the audio output may keep looping if we don't
  1416.        if(m_speed == DVD_PLAYSPEED_NORMAL)
  1417. +      {
  1418.          m_dvdAudio.Flush();
  1419. +        if (m_bAudio2)
  1420. +          m_dvdAudio2.Flush();
  1421. +      }
  1422.  
  1423.        continue;
  1424.      }
  1425. @@ -544,12 +633,34 @@
  1426.      packetadded = true;
  1427.  
  1428.      // we have succesfully decoded an audio frame, setup renderer to match
  1429. +    bool bCreate1 = false, bCreate2 = false;
  1430. +    double ct1 = 0.0, ct2 = 0.0;
  1431.      if (!m_dvdAudio.IsValidFormat(audioframe))
  1432.      {
  1433.        m_dvdAudio.Destroy();
  1434.        if(!m_dvdAudio.Create(audioframe, m_streaminfo.codec))
  1435.          CLog::Log(LOGERROR, "%s - failed to create audio renderer", __FUNCTION__);
  1436. -      m_messageQueue.SetMaxTimeSize(8.0 - m_dvdAudio.GetCacheTotal());
  1437. +      bCreate1 = true;
  1438. +    }
  1439. +    ct1 = m_dvdAudio.GetCacheTotal();
  1440. +    if (m_bAudio2)
  1441. +    {
  1442. +      if (!m_dvdAudio2.IsValidFormat(audioframe2))
  1443. +      {
  1444. +        m_dvdAudio2.Destroy();
  1445. +        if(!m_dvdAudio2.Create(audioframe2, m_streaminfo.codec, m_bAudio2))
  1446. +          CLog::Log(LOGERROR, "%s - failed to create 2nd audio renderer", __FUNCTION__);
  1447. +        bCreate2 = true;
  1448. +      }
  1449. +      ct2 = m_dvdAudio2.GetCacheTotal();
  1450. +    }
  1451. +    if(m_bAudio2 && (bCreate1 || bCreate2))
  1452. +    {
  1453. +      m_messageQueue.SetMaxTimeSize(8.0 - std::min(ct1, ct2));
  1454. +    }
  1455. +    else if(!m_bAudio2 && bCreate1)
  1456. +    {
  1457. +      m_messageQueue.SetMaxTimeSize(8.0 - ct1);
  1458.      }
  1459.  
  1460.      if( result & DECODE_FLAG_DROP )
  1461. @@ -573,10 +684,12 @@
  1462.        SetSyncType(audioframe.passthrough);
  1463.  
  1464.        // add any packets play
  1465. -      packetadded = OutputPacket(audioframe);
  1466. +      if (m_bAudio2)
  1467. +        HandleSyncAudio2(audioframe2);
  1468. +      packetadded = OutputPacket(audioframe, audioframe2);
  1469.  
  1470.        // we are not running until something is cached in output device
  1471. -      if(m_stalled && m_dvdAudio.GetCacheTime() > 0.0)
  1472. +      if(m_stalled && m_dvdAudio.GetCacheTime() > 0.0 && (!m_bAudio2 || m_dvdAudio2.GetCacheTime() > 0.0))
  1473.          m_stalled = false;
  1474.      }
  1475.  
  1476. @@ -712,11 +825,49 @@
  1477.    }
  1478.  }
  1479.  
  1480. -bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe)
  1481. +void CDVDPlayerAudio::HandleSyncAudio2(DVDAudioFrame &audioframe2)
  1482. +{
  1483. +  double dtm1 = m_dvdAudio.GetDelay();
  1484. +  double dtm2 = m_dvdAudio2.GetDelay();
  1485. +  double ddiff = (dtm1 - dtm2);
  1486. +
  1487. +  m_audiodiff = ddiff / DVD_TIME_BASE;
  1488. +
  1489. +  double mt = 50000.0/audioframe2.duration;
  1490. +  if (mt < 1.0) mt = 1.0;
  1491. +  double thresholdhigh = ((int)mt)*audioframe2.duration;
  1492. +  double thresholdlow = audioframe2.duration;
  1493. +  if (mt-((int)mt) >= 0.5)
  1494. +    thresholdhigh+=audioframe2.duration;
  1495. +
  1496. +  if (ddiff >= thresholdhigh)
  1497. +  {
  1498. +    m_dvdAudio2.Pause();
  1499. +    m_bAudio2Pause = true;
  1500. +  }
  1501. +  else if (m_bAudio2Pause && ddiff <= thresholdlow)
  1502. +  {
  1503. +    m_dvdAudio2.Resume();
  1504. +    m_bAudio2Pause = false;
  1505. +  }
  1506. +
  1507. +  if (ddiff <= -thresholdhigh)
  1508. +  {
  1509. +    m_bAudio2Stuck = true;
  1510. +  }
  1511. +  else if (m_bAudio2Stuck && ddiff >= -thresholdlow)
  1512. +  {
  1513. +    m_bAudio2Stuck = false;
  1514. +  }
  1515. +}
  1516. +
  1517. +bool CDVDPlayerAudio::OutputPacket(DVDAudioFrame &audioframe, DVDAudioFrame &audioframe2)
  1518.  {
  1519.    if (m_synctype == SYNC_DISCON)
  1520.    {
  1521.      m_dvdAudio.AddPackets(audioframe);
  1522. +    if (m_bAudio2 && !m_bAudio2Stuck)
  1523. +      m_dvdAudio2.AddPackets(audioframe2);
  1524.    }
  1525.    else if (m_synctype == SYNC_SKIPDUP)
  1526.    {
  1527. @@ -726,6 +877,8 @@
  1528.        if (!m_prevskipped)
  1529.        {
  1530.          m_dvdAudio.AddPackets(audioframe);
  1531. +        if (m_bAudio2 && !m_bAudio2Stuck)
  1532. +          m_dvdAudio2.AddPackets(audioframe2);
  1533.          m_skipdupcount++;
  1534.        }
  1535.      }
  1536. @@ -733,11 +886,18 @@
  1537.      {
  1538.        m_dvdAudio.AddPackets(audioframe);
  1539.        m_dvdAudio.AddPackets(audioframe);
  1540. +      if (m_bAudio2 && !m_bAudio2Stuck)
  1541. +      {
  1542. +        m_dvdAudio2.AddPackets(audioframe2);
  1543. +        m_dvdAudio2.AddPackets(audioframe2);
  1544. +      }
  1545.        m_skipdupcount--;
  1546.      }
  1547.      else if (m_skipdupcount == 0)
  1548.      {
  1549.        m_dvdAudio.AddPackets(audioframe);
  1550. +      if (m_bAudio2 && !m_bAudio2Stuck)
  1551. +        m_dvdAudio2.AddPackets(audioframe2);
  1552.      }
  1553.    }
  1554.    else if (m_synctype == SYNC_RESAMPLE)
  1555. @@ -762,6 +922,8 @@
  1556.      while(m_resampler.Retrieve(audioframe, audioframe.pts))
  1557.      {
  1558.        m_dvdAudio.AddPackets(audioframe);
  1559. +      if (m_bAudio2 && !m_bAudio2Stuck)
  1560. +        m_dvdAudio2.AddPackets(audioframe2);
  1561.        packetadded = true;
  1562.      }
  1563.      return packetadded;
  1564. @@ -812,6 +974,8 @@
  1565.    std::ostringstream s;
  1566.    s << "aq:"     << setw(2) << min(99,m_messageQueue.GetLevel()) << "%";
  1567.    s << ", kB/s:" << fixed << setprecision(2) << (double)GetAudioBitrate() / 1024.0;
  1568. +  if (m_bAudio2)
  1569. +    s << ", a1/a2:" << fixed << setprecision(3) << m_audiodiff;
  1570.    return s.str();
  1571.  }
  1572.  
  1573. @@ -822,5 +986,5 @@
  1574.  
  1575.  bool CDVDPlayerAudio::IsPassthrough() const
  1576.  {
  1577. -  return m_pAudioCodec && m_pAudioCodec->NeedPassthrough();
  1578. +  return m_pAudioCodec && m_pAudioCodec->NeedPassthrough() && (!m_bAudio2 || (m_pAudioCodec2 && m_pAudioCodec2->NeedPassthrough()));
  1579.  }
  1580. diff -Naur xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDPlayerAudio.h xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDPlayerAudio.h
  1581. --- xbmc-10.1-Dharma/xbmc/cores/dvdplayer/DVDPlayerAudio.h  2011-10-31 13:42:31.632451326 +0000
  1582. +++ xbmc-10.1-Dharma.patch/xbmc/cores/dvdplayer/DVDPlayerAudio.h    2011-10-31 13:41:06.896213263 +0000
  1583. @@ -107,8 +107,8 @@
  1584.    bool AcceptsData()                                    { return !m_messageQueue.IsFull(); }
  1585.    void SendMessage(CDVDMsg* pMsg, int priority = 0)     { m_messageQueue.Put(pMsg, priority); }
  1586.  
  1587. -  void SetVolume(long nVolume)                          { m_dvdAudio.SetVolume(nVolume); }
  1588. -  void SetDynamicRangeCompression(long drc)             { m_dvdAudio.SetDynamicRangeCompression(drc); }
  1589. +  void SetVolume(long nVolume)                          { m_dvdAudio.SetVolume(nVolume); if(m_bAudio2) m_dvdAudio2.SetVolume(nVolume); }
  1590. +  void SetDynamicRangeCompression(long drc)             { m_dvdAudio.SetDynamicRangeCompression(drc); if(m_bAudio2) m_dvdAudio2.SetDynamicRangeCompression(drc); }
  1591.  
  1592.    std::string GetPlayerInfo();
  1593.    int GetAudioBitrate();
  1594. @@ -131,7 +131,7 @@
  1595.    virtual void OnExit();
  1596.    virtual void Process();
  1597.  
  1598. -  int DecodeFrame(DVDAudioFrame &audioframe, bool bDropPacket);
  1599. +  int DecodeFrame(DVDAudioFrame &audioframe, DVDAudioFrame &audioframe2, bool bDropPacket);
  1600.  
  1601.    // tries to open a decoder for the given data.
  1602.    bool OpenDecoder(CDVDStreamInfo &hint, BYTE* buffer = NULL, unsigned int size = 0);
  1603. @@ -167,8 +167,10 @@
  1604.    } m_decode;
  1605.  
  1606.    CDVDAudio m_dvdAudio; // audio output device
  1607. +  CDVDAudio m_dvdAudio2; // audio output device 2
  1608.    CDVDClock* m_pClock; // dvd master clock
  1609.    CDVDAudioCodec* m_pAudioCodec; // audio codec
  1610. +  CDVDAudioCodec* m_pAudioCodec2; // audio codec 2
  1611.    BitstreamStats m_audioStats;
  1612.  
  1613.    int     m_speed;
  1614. @@ -179,7 +181,7 @@
  1615.  
  1616.    CDVDPlayerResampler m_resampler;
  1617.  
  1618. -  bool OutputPacket(DVDAudioFrame &audioframe);
  1619. +  bool OutputPacket(DVDAudioFrame &audioframe, DVDAudioFrame &audioframe2);
  1620.  
  1621.    //SYNC_DISCON, SYNC_SKIPDUP, SYNC_RESAMPLE
  1622.    int    m_synctype;
  1623. @@ -193,6 +195,7 @@
  1624.  
  1625.    void   SetSyncType(bool passthrough);
  1626.    void   HandleSyncError(double duration);
  1627. +  void   HandleSyncAudio2(DVDAudioFrame &audioframe2);
  1628.    double m_errorbuff; //place to store average errors
  1629.    int    m_errorcount;//number of errors stored
  1630.    bool   m_syncclock;
  1631. @@ -201,5 +204,10 @@
  1632.    int    m_skipdupcount; //counter for skip/duplicate synctype
  1633.    bool   m_prevskipped;
  1634.    double m_maxspeedadjust;
  1635. +
  1636. +  bool   m_bAudio2;
  1637. +  bool   m_bAudio2Stuck;
  1638. +  bool   m_bAudio2Pause;
  1639. +  double m_audiodiff;
  1640.  };
  1641.  
  1642. diff -Naur xbmc-10.1-Dharma/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp xbmc-10.1-Dharma.patch/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp
  1643. --- xbmc-10.1-Dharma/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp   2011-10-31 13:42:26.604081158 +0000
  1644. +++ xbmc-10.1-Dharma.patch/xbmc/cores/ExternalPlayer/ExternalPlayer.cpp 2011-10-31 13:41:01.275799493 +0000
  1645. @@ -254,6 +254,13 @@
  1646.      g_audioContext.SetActiveDevice(CAudioContext::NONE);
  1647.    }
  1648.  
  1649. +  int iActiveDevice2 = g_audioContext2.GetActiveDevice();
  1650. +  if (iActiveDevice2 != CAudioContext::NONE)
  1651. +  {
  1652. +    CLog::Log(LOGNOTICE, "%s: Releasing 2nd audio device %d", __FUNCTION__, iActiveDevice2);
  1653. +    g_audioContext2.SetActiveDevice(CAudioContext::NONE);
  1654. +  }
  1655. +
  1656.  #if defined(_WIN32)
  1657.    if (m_warpcursor)
  1658.    {
  1659. @@ -371,6 +378,12 @@
  1660.      g_audioContext.SetActiveDevice(iActiveDevice);
  1661.    }
  1662.  
  1663. +  if (iActiveDevice2 != CAudioContext::NONE)
  1664. +  {
  1665. +    CLog::Log(LOGNOTICE, "%s: Reclaiming 2nd audio device %d", __FUNCTION__, iActiveDevice2);
  1666. +    g_audioContext2.SetActiveDevice(iActiveDevice2);
  1667. +  }
  1668. +
  1669.    if (!ret || (m_playOneStackItem && g_application.CurrentFileItem().IsStack()))
  1670.      m_callback.OnPlayBackStopped();
  1671.    else
  1672. diff -Naur xbmc-10.1-Dharma/xbmc/cores/paplayer/PAPlayer.cpp xbmc-10.1-Dharma.patch/xbmc/cores/paplayer/PAPlayer.cpp
  1673. --- xbmc-10.1-Dharma/xbmc/cores/paplayer/PAPlayer.cpp   2011-10-31 13:42:33.218568090 +0000
  1674. +++ xbmc-10.1-Dharma.patch/xbmc/cores/paplayer/PAPlayer.cpp 2011-10-31 13:41:01.321802880 +0000
  1675. @@ -75,8 +75,15 @@
  1676.  
  1677.      m_pAudioDecoder[i] = NULL;
  1678.      m_pcmBuffer[i] = NULL;
  1679. +    m_pcmBufLen[i] = 0;
  1680.      m_bufferPos[i] = 0;
  1681.      m_Chunklen[i]  = PACKET_SIZE;
  1682. +
  1683. +    m_pAudioDecoder2[i] = NULL;
  1684. +    m_pcmBuffer2[i] = NULL;
  1685. +    m_pcmBufLen2[i] = 0;
  1686. +    m_bufferPos2[i] = 0;
  1687. +    m_Chunklen2[i]  = PACKET_SIZE;
  1688.    }
  1689.  
  1690.    m_currentStream = 0;
  1691. @@ -118,7 +125,7 @@
  1692.  
  1693.    m_crossFading = g_guiSettings.GetInt("musicplayer.crossfade");
  1694.    //WASAPI doesn't support multiple streams, no crossfading for cdda, cd-reading goes mad and no crossfading for last.fm doesn't like two connections
  1695. -  if (file.IsCDDA() || file.IsLastFM() || g_guiSettings.GetString("audiooutput.audiodevice").find("wasapi:") != CStdString::npos) m_crossFading = 0;
  1696. +  if (file.IsCDDA() || file.IsLastFM() || g_guiSettings.GetString("audiooutput.audiodevice").find("wasapi:") != CStdString::npos || g_guiSettings.GetString("audiooutput2.audiodevice").find("wasapi:") != CStdString::npos) m_crossFading = 0;
  1697.    if (m_crossFading && IsPlaying())
  1698.    {
  1699.      //do a short crossfade on trackskip
  1700. @@ -200,6 +207,7 @@
  1701.            (m_currentFile->GetMusicInfoTag()->GetTrackNumber() == file.GetMusicInfoTag()->GetTrackNumber() - 1)
  1702.          )
  1703.          || g_guiSettings.GetString("audiooutput.audiodevice").find("wasapi:") != CStdString::npos
  1704. +        || g_guiSettings.GetString("audiooutput2.audiodevice").find("wasapi:") != CStdString::npos
  1705.        )
  1706.      )
  1707.      {
  1708. @@ -297,7 +305,10 @@
  1709.    m_nextFile->Reset();
  1710.  
  1711.    if(bAudioDevice)
  1712. +  {
  1713.      g_audioContext.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  1714. +    g_audioContext2.SetActiveDevice(CAudioContext::DEFAULT_DEVICE);
  1715. +  }
  1716.    else
  1717.      FlushStreams();
  1718.  
  1719. @@ -306,15 +317,8 @@
  1720.  
  1721.  void PAPlayer::FreeStream(int stream)
  1722.  {
  1723. -  if (m_pAudioDecoder[stream])
  1724. -  {
  1725. -    DrainStream(stream);
  1726. -
  1727. -    delete m_pAudioDecoder[stream];
  1728. -    free(m_pcmBuffer[stream]);
  1729. -  }
  1730. -  m_pAudioDecoder[stream] = NULL;
  1731. -  m_pcmBuffer[stream] = NULL;
  1732. +  FreeStreamRenderer(stream, false);
  1733. +  FreeStreamRenderer(stream, true);
  1734.  
  1735.    if (m_packet[stream][0].packet)
  1736.      free(m_packet[stream][0].packet);
  1737. @@ -327,41 +331,123 @@
  1738.    m_resampler[stream].DeInitialize();
  1739.  }
  1740.  
  1741. -void PAPlayer::DrainStream(int stream)
  1742. +void PAPlayer::FreeStreamRenderer(int stream, bool bAudio2)
  1743.  {
  1744. -  if(m_bStopPlaying || m_pAudioDecoder[1 - stream])
  1745. +  if (!bAudio2)
  1746.    {
  1747. -    m_pAudioDecoder[stream]->Stop();
  1748. -    return;
  1749. -  }
  1750. -
  1751. -  DWORD silence = m_pAudioDecoder[stream]->GetChunkLen() - m_bufferPos[stream] % m_pAudioDecoder[stream]->GetChunkLen();
  1752. +    if (m_pAudioDecoder[stream])
  1753. +    {
  1754. +      DrainStream(stream, bAudio2);
  1755.  
  1756. -  if(silence > 0 && m_bufferPos[stream] > 0)
  1757. +      delete m_pAudioDecoder[stream];
  1758. +      free(m_pcmBuffer[stream]);
  1759. +    }
  1760. +    m_pAudioDecoder[stream] = NULL;
  1761. +    m_pcmBuffer[stream] = NULL;
  1762. +    m_pcmBufLen[stream] = 0;
  1763. +  }
  1764. +  else
  1765.    {
  1766. -    CLog::Log(LOGDEBUG, "PAPlayer: Drain - adding %d bytes of silence, real pcmdata size: %d, chunk size: %d", silence, m_bufferPos[stream], m_pAudioDecoder[stream]->GetChunkLen());
  1767. -    memset(m_pcmBuffer[stream] + m_bufferPos[stream], 0, silence);
  1768. -    m_bufferPos[stream] += silence;
  1769. +    if (m_pAudioDecoder2[stream])
  1770. +    {
  1771. +      DrainStream(stream, bAudio2);
  1772. +
  1773. +      delete m_pAudioDecoder2[stream];
  1774. +      free(m_pcmBuffer2[stream]);
  1775. +    }
  1776. +    m_pAudioDecoder2[stream] = NULL;
  1777. +    m_pcmBuffer2[stream] = NULL;
  1778. +    m_pcmBufLen2[stream] = 0;
  1779.    }
  1780. +}
  1781. +
  1782. +void PAPlayer::DrainStream(int stream)
  1783. +{
  1784. +  DrainStream(stream, false);
  1785. +  DrainStream(stream, true);
  1786. +}
  1787.  
  1788. -  DWORD added = 0;
  1789. -  while(m_bufferPos[stream] - added >= m_pAudioDecoder[stream]->GetChunkLen())
  1790. +void PAPlayer::DrainStream(int stream, bool bAudio2)
  1791. +{
  1792. +  if (!bAudio2)
  1793.    {
  1794. -    added += m_pAudioDecoder[stream]->AddPackets(m_pcmBuffer[stream] + added, m_bufferPos[stream] - added);
  1795. -    Sleep(1);
  1796. +    if(m_bStopPlaying || m_pAudioDecoder[1 - stream])
  1797. +    {
  1798. +      m_pAudioDecoder[stream]->Stop();
  1799. +      return;
  1800. +    }
  1801. +
  1802. +    DWORD silence = m_pAudioDecoder[stream]->GetChunkLen() - m_bufferPos[stream] % m_pAudioDecoder[stream]->GetChunkLen();
  1803. +
  1804. +    if(silence > 0 && m_bufferPos[stream] > 0)
  1805. +    {
  1806. +      CLog::Log(LOGDEBUG, "PAPlayer: Drain - adding %d bytes of silence, real pcmdata size: %d, chunk size: %d", silence, m_bufferPos[stream], m_pAudioDecoder[stream]->GetChunkLen());
  1807. +      memset(m_pcmBuffer[stream] + m_bufferPos[stream], 0, silence);
  1808. +      m_bufferPos[stream] += silence;
  1809. +    }
  1810. +
  1811. +    DWORD added = 0;
  1812. +    while(m_bufferPos[stream] - added >= m_pAudioDecoder[stream]->GetChunkLen())
  1813. +    {
  1814. +      added += m_pAudioDecoder[stream]->AddPackets(m_pcmBuffer[stream] + added, m_bufferPos[stream] - added);
  1815. +      Sleep(1);
  1816. +    }
  1817. +    m_bufferPos[stream] = 0;
  1818. +
  1819. +    m_pAudioDecoder[stream]->WaitCompletion();
  1820.    }
  1821. -  m_bufferPos[stream] = 0;
  1822. +  else
  1823. +  {
  1824. +    if(m_bStopPlaying || m_pAudioDecoder2[1 - stream])
  1825. +    {
  1826. +      m_pAudioDecoder2[stream]->Stop();
  1827. +      return;
  1828. +    }
  1829. +
  1830. +    DWORD silence = m_pAudioDecoder2[stream]->GetChunkLen() - m_bufferPos2[stream] % m_pAudioDecoder2[stream]->GetChunkLen();
  1831. +
  1832. +    if(silence > 0 && m_bufferPos2[stream] > 0)
  1833. +    {
  1834. +      CLog::Log(LOGDEBUG, "PAPlayer: 2nd Audio Drain - adding %d bytes of silence, real pcmdata size: %d, chunk size: %d", silence, m_bufferPos2[stream], m_pAudioDecoder2[stream]->GetChunkLen());
  1835. +      memset(m_pcmBuffer2[stream] + m_bufferPos2[stream], 0, silence);
  1836. +      m_bufferPos2[stream] += silence;
  1837. +    }
  1838. +
  1839. +    DWORD added = 0;
  1840. +    while(m_bufferPos2[stream] - added >= m_pAudioDecoder2[stream]->GetChunkLen())
  1841. +    {
  1842. +      added += m_pAudioDecoder2[stream]->AddPackets(m_pcmBuffer2[stream] + added, m_bufferPos2[stream] - added);
  1843. +      Sleep(1);
  1844. +    }
  1845. +    m_bufferPos2[stream] = 0;
  1846.  
  1847. -  m_pAudioDecoder[stream]->WaitCompletion();
  1848. +    m_pAudioDecoder2[stream]->WaitCompletion();
  1849. +  }
  1850.  }
  1851.  
  1852.  bool PAPlayer::CreateStream(int num, unsigned int channels, unsigned int samplerate, unsigned int bitspersample, CStdString codec)
  1853.  {
  1854.    unsigned int outputSampleRate = (channels <= 2 && g_advancedSettings.m_musicResample) ? g_advancedSettings.m_musicResample : samplerate;
  1855.  
  1856. +  bool bCreate2 = true;
  1857. +  if (g_guiSettings.GetInt("audiooutput2.mode") == AUDIO_NONE)
  1858. +  {
  1859. +    if (m_pAudioDecoder2[num] != NULL)
  1860. +    {
  1861. +      CLog::Log(LOGDEBUG, "PAPlayer: 2nd audio renderer now disabled");
  1862. +      FreeStreamRenderer(num, true);
  1863. +    }
  1864. +   bCreate2 = false;
  1865. +  }
  1866. +
  1867.    if (m_pAudioDecoder[num] != NULL && m_channelCount[num] == channels && m_sampleRate[num] == outputSampleRate /* && m_bitsPerSample[num] == bitspersample */)
  1868.    {
  1869.      CLog::Log(LOGDEBUG, "PAPlayer: Using existing audio renderer");
  1870. +    if( bCreate2 && m_pAudioDecoder2[num] != NULL )
  1871. +    {
  1872. +      CLog::Log(LOGDEBUG, "PAPlayer: Using existing 2nd audio renderer");
  1873. +     bCreate2 = false;
  1874. +    }
  1875.    }
  1876.    else
  1877.    {
  1878. @@ -385,17 +471,90 @@
  1879.        false                 //bPassthrough
  1880.      );
  1881.  
  1882. -    if (!m_pAudioDecoder[num]) return false;
  1883. +    if (m_pAudioDecoder[num] != NULL)
  1884. +    {
  1885. +      m_pcmBufLen[num] = (m_pAudioDecoder[num]->GetChunkLen() + PACKET_SIZE);
  1886. +      m_pcmBuffer[num] = (unsigned char*)malloc(m_pcmBufLen[num]);
  1887. +      m_bufferPos[num] = 0;
  1888. +      m_latency[num]   = m_pAudioDecoder[num]->GetDelay();
  1889. +      m_Chunklen[num]  = std::max(PACKET_SIZE, (int)m_pAudioDecoder[num]->GetChunkLen());
  1890. +      m_packet[num][0].packet = (BYTE*)malloc(PACKET_SIZE * PACKET_COUNT);
  1891. +      for (int i = 1; i < PACKET_COUNT ; i++)
  1892. +       m_packet[num][i].packet = m_packet[num][i - 1].packet + PACKET_SIZE;
  1893. +    }
  1894. +    else
  1895. +    {
  1896. +      CLog::Log(LOGDEBUG, "PAPlayer: Creating new audio renderer failed");
  1897. +    }
  1898. +  }
  1899.  
  1900. -    m_pcmBuffer[num] = (unsigned char*)malloc((m_pAudioDecoder[num]->GetChunkLen() + PACKET_SIZE));
  1901. -    m_bufferPos[num] = 0;
  1902. -    m_latency[num]   = m_pAudioDecoder[num]->GetDelay();
  1903. -    m_Chunklen[num]  = std::max(PACKET_SIZE, (int)m_pAudioDecoder[num]->GetChunkLen());
  1904. -    m_packet[num][0].packet = (BYTE*)malloc(PACKET_SIZE * PACKET_COUNT);
  1905. -    for (int i = 1; i < PACKET_COUNT ; i++)
  1906. -      m_packet[num][i].packet = m_packet[num][i - 1].packet + PACKET_SIZE;
  1907. +  if (bCreate2)
  1908. +  {
  1909. +    CLog::Log(LOGDEBUG, "PAPlayer: Creating new 2nd audio renderer");
  1910. +
  1911. +    /* Open the device */
  1912. +    m_pAudioDecoder2[num] = CAudioRendererFactory::Create(
  1913. +      NULL                , //pCallback
  1914. +      m_channelCount [num], //iChannels
  1915. +      m_channelMap   [num], //channelMap
  1916. +      m_sampleRate   [num], //uiSamplesPerSec
  1917. +      m_bitsPerSample[num], //uiBitsPerSample
  1918. +      false               , //bResample
  1919. +      true                , //bIsMusic
  1920. +      false               , //bPassthrough
  1921. +      true                  //2nd renderer
  1922. +    );
  1923. +
  1924. +    if (m_pAudioDecoder2[num] != NULL)
  1925. +    {
  1926. +      m_pcmBufLen2[num] = (m_pAudioDecoder2[num]->GetChunkLen() + PACKET_SIZE);
  1927. +      m_pcmBuffer2[num] = (unsigned char*)malloc(m_pcmBufLen2[num]);
  1928. +      m_bufferPos2[num] = 0;
  1929. +      m_latency2[num] = m_pAudioDecoder2[num]->GetDelay();
  1930. +      m_Chunklen2[num]  = std::max(PACKET_SIZE, (int)m_pAudioDecoder2[num]->GetChunkLen());
  1931. +      if (m_packet[num][0].packet == NULL)
  1932. +      {
  1933. +        m_packet[num][0].packet = (BYTE*)malloc(PACKET_SIZE * PACKET_COUNT);
  1934. +        for (int i = 1; i < PACKET_COUNT ; i++)
  1935. +          m_packet[num][i].packet = m_packet[num][i - 1].packet + PACKET_SIZE;
  1936. +      }
  1937. +    }
  1938. +    else
  1939. +    {
  1940. +      CLog::Log(LOGDEBUG, "PAPlayer: Creating new 2nd audio renderer failed");
  1941. +    }
  1942.    }
  1943. -  
  1944. +
  1945. +  int maxChunklen = std::max(m_Chunklen[num], m_Chunklen2[num]);
  1946. +  unsigned int pcmBufLen = (std::max(PACKET_SIZE, maxChunklen)) * 4 + PACKET_SIZE;
  1947. +  if (pcmBufLen > m_pcmBufLen[num])
  1948. +  {
  1949. +    unsigned char* bufTemp = m_pcmBuffer[num];
  1950. +    if (bufTemp)
  1951. +    {
  1952. +      m_pcmBuffer[num] = (unsigned char*)malloc(pcmBufLen);
  1953. +      memcpy (m_pcmBuffer[num], bufTemp, m_pcmBufLen[num]);
  1954. +      free(bufTemp);
  1955. +      m_pcmBufLen[num] = pcmBufLen;
  1956. +    }
  1957. +  }
  1958. +  if (pcmBufLen > m_pcmBufLen2[num])
  1959. +  {
  1960. +    unsigned char* bufTemp = m_pcmBuffer2[num];
  1961. +    if (bufTemp)
  1962. +    {
  1963. +      m_pcmBuffer2[num] = (unsigned char*)malloc(pcmBufLen);
  1964. +      memcpy (m_pcmBuffer2[num], bufTemp, m_pcmBufLen2[num]);
  1965. +      free(bufTemp);
  1966. +      m_pcmBufLen2[num] = pcmBufLen;
  1967. +    }
  1968. +  }
  1969. +
  1970. +  if (m_pAudioDecoder[num] == NULL && m_pAudioDecoder2[num] == NULL)
  1971. +  {
  1972. +    return false;
  1973. +  }
  1974. +
  1975.    // set initial volume
  1976.    SetStreamVolume(num, g_settings.m_nVolumeLevel);
  1977.  
  1978. @@ -426,6 +585,12 @@
  1979.      if (m_currentlyCrossFading && m_pAudioDecoder[1 - m_currentStream])
  1980.        m_pAudioDecoder[1 - m_currentStream]->Pause();
  1981.  
  1982. +    if (m_pAudioDecoder2[m_currentStream])
  1983. +      m_pAudioDecoder2[m_currentStream]->Pause();
  1984. +
  1985. +    if (m_currentlyCrossFading && m_pAudioDecoder2[1 - m_currentStream])
  1986. +      m_pAudioDecoder2[1 - m_currentStream]->Pause();
  1987. +
  1988.      m_callback.OnPlayBackPaused();
  1989.      CLog::Log(LOGDEBUG, "PAPlayer: Playback paused");
  1990.    }
  1991. @@ -437,6 +602,12 @@
  1992.      if (m_currentlyCrossFading && m_pAudioDecoder[1 - m_currentStream])
  1993.        m_pAudioDecoder[1 - m_currentStream]->Resume();
  1994.  
  1995. +    if (m_pAudioDecoder2[m_currentStream])
  1996. +      m_pAudioDecoder2[m_currentStream]->Resume();
  1997. +
  1998. +    if (m_currentlyCrossFading && m_pAudioDecoder2[1 - m_currentStream])
  1999. +      m_pAudioDecoder2[1 - m_currentStream]->Resume();
  2000. +
  2001.      m_callback.OnPlayBackResumed();
  2002.      CLog::Log(LOGDEBUG, "PAPlayer: Playback resumed");
  2003.    }
  2004. @@ -446,6 +617,8 @@
  2005.  {
  2006.    if (m_pAudioDecoder[m_currentStream])
  2007.      m_pAudioDecoder[m_currentStream]->SetCurrentVolume(nVolume);
  2008. +  if (m_pAudioDecoder2[m_currentStream])
  2009. +    m_pAudioDecoder2[m_currentStream]->SetCurrentVolume(nVolume);
  2010.  }
  2011.  
  2012.  void PAPlayer::SetDynamicRangeCompression(long drc)
  2013. @@ -554,7 +727,7 @@
  2014.      {
  2015.        if (((GetTotalTime64() - GetTime() < m_crossFading * 1000L) || (m_forceFadeToNext)) && !m_currentlyCrossFading)
  2016.        { // request the next file from our application
  2017. -        if (m_decoder[1 - m_currentDecoder].GetStatus() == STATUS_QUEUED && m_pAudioDecoder[1 - m_currentStream])
  2018. +        if (m_decoder[1 - m_currentDecoder].GetStatus() == STATUS_QUEUED && (m_pAudioDecoder[1 - m_currentStream] || m_pAudioDecoder2[1 - m_currentStream]))
  2019.          {
  2020.            m_currentlyCrossFading = true;
  2021.            if (m_forceFadeToNext)
  2022. @@ -571,7 +744,8 @@
  2023.            m_currentStream = 1 - m_currentStream;
  2024.            CLog::Log(LOGDEBUG, "Starting Crossfade - resuming stream %i", m_currentStream);
  2025.  
  2026. -          m_pAudioDecoder[m_currentStream]->Resume();
  2027. +          if (m_pAudioDecoder[m_currentStream]) m_pAudioDecoder[m_currentStream]->Resume();
  2028. +          if (m_pAudioDecoder2[m_currentStream]) m_pAudioDecoder2[m_currentStream]->Resume();
  2029.  
  2030.            m_callback.OnPlayBackStarted();
  2031.            m_timeOffset = m_nextFile->m_lStartOffset * 1000 / 75;
  2032. @@ -614,7 +788,8 @@
  2033.                  CLog::Log(LOGERROR, "PAPlayer: Error creating stream!");
  2034.                  return false;
  2035.                }
  2036. -              m_pAudioDecoder[m_currentStream]->Resume();
  2037. +              if (m_pAudioDecoder[m_currentStream]) m_pAudioDecoder[m_currentStream]->Resume();
  2038. +              if (m_pAudioDecoder2[m_currentStream]) m_pAudioDecoder2[m_currentStream]->Resume();
  2039.              }
  2040.              else if (samplerate != samplerate2 || bitspersample != bitspersample2)
  2041.              {
  2042. @@ -743,10 +918,15 @@
  2043.  
  2044.        if (retVal == RET_SLEEP && retVal2 == RET_SLEEP)
  2045.        {
  2046. -        float maximumSleepTime = m_pAudioDecoder[m_currentStream]->GetCacheTime();
  2047. -        
  2048. +        float maximumSleepTime = 0.0;
  2049. +        if (m_pAudioDecoder[m_currentStream])
  2050. +          maximumSleepTime = std::min(maximumSleepTime, m_pAudioDecoder[m_currentStream]->GetCacheTime());
  2051.          if (m_pAudioDecoder[1 - m_currentStream])
  2052.            maximumSleepTime = std::min(maximumSleepTime, m_pAudioDecoder[1 - m_currentStream]->GetCacheTime());
  2053. +        if (m_pAudioDecoder2[m_currentStream])
  2054. +          maximumSleepTime = std::min(maximumSleepTime, m_pAudioDecoder2[m_currentStream]->GetCacheTime());
  2055. +        if (m_pAudioDecoder2[1 - m_currentStream])
  2056. +          maximumSleepTime = std::min(maximumSleepTime, m_pAudioDecoder2[1 - m_currentStream]->GetCacheTime());
  2057.  
  2058.          int sleep = std::max((int)((maximumSleepTime / 2.0f) * 1000.0f), 1);
  2059.  
  2060. @@ -912,6 +1092,12 @@
  2061.        m_pAudioDecoder[stream]->Resume();
  2062.        m_bufferPos[stream] = 0;
  2063.      }
  2064. +    if (m_pAudioDecoder2[stream] && m_packet[stream])
  2065. +    {
  2066. +      m_pAudioDecoder2[stream]->Stop();
  2067. +      m_pAudioDecoder2[stream]->Resume();
  2068. +      m_bufferPos2[stream] = 0;
  2069. +    }
  2070.    }
  2071.  }
  2072.  
  2073. @@ -965,12 +1151,13 @@
  2074.  
  2075.  void PAPlayer::SetStreamVolume(int stream, long nVolume)
  2076.  {
  2077. -  m_pAudioDecoder[stream]->SetCurrentVolume(nVolume);
  2078. +  if(m_pAudioDecoder[stream] != NULL) m_pAudioDecoder[stream]->SetCurrentVolume(nVolume);
  2079. +  if(m_pAudioDecoder2[stream] != NULL) m_pAudioDecoder2[stream]->SetCurrentVolume(nVolume);
  2080.  }
  2081.  
  2082.  bool PAPlayer::AddPacketsToStream(int stream, CAudioDecoder &dec)
  2083.  {
  2084. -  if (!m_pAudioDecoder[stream] || dec.GetStatus() == STATUS_NO_FILE)
  2085. +  if ((!m_pAudioDecoder[stream] && !m_pAudioDecoder2[stream]) || dec.GetStatus() == STATUS_NO_FILE)
  2086.      return false;
  2087.  
  2088.    bool ret = false;
  2089. @@ -980,7 +1167,9 @@
  2090.      m_resampler[stream].PutFloatData((float *)dec.GetData(amount), amount);
  2091.      ret = true;
  2092.    }
  2093. -  else if (m_Chunklen[stream] > m_pAudioDecoder[stream]->GetSpace())
  2094. +  else if (( m_pAudioDecoder[stream] && m_pAudioDecoder2[stream] && m_Chunklen[stream] > m_pAudioDecoder[stream]->GetSpace() && m_Chunklen2[stream] > m_pAudioDecoder2[stream]->GetSpace()) ||
  2095. +           ( m_pAudioDecoder[stream] && !m_pAudioDecoder2[stream] && m_Chunklen[stream] > m_pAudioDecoder[stream]->GetSpace()) ||
  2096. +           ( !m_pAudioDecoder[stream] && m_pAudioDecoder2[stream] && m_Chunklen2[stream] > m_pAudioDecoder2[stream]->GetSpace()))
  2097.    { // resampler probably have data but wait until we can send atleast a packet
  2098.      ret = false;
  2099.    }
  2100. @@ -994,20 +1183,65 @@
  2101.      int len = m_packet[stream][0].length;
  2102.      StreamCallback(&m_packet[stream][0]);
  2103.  
  2104. -    memcpy(m_pcmBuffer[stream]+m_bufferPos[stream], pcmPtr, len);
  2105. -    m_bufferPos[stream] += len;
  2106. -
  2107. -    while (m_bufferPos[stream] >= (int)m_pAudioDecoder[stream]->GetChunkLen())
  2108. +    if (m_pAudioDecoder[stream])
  2109.      {
  2110. -      int rtn = m_pAudioDecoder[stream]->AddPackets(m_pcmBuffer[stream], m_bufferPos[stream]);
  2111. -      if (rtn == 0) //no pcm data added
  2112. +      if ((int)m_pcmBufLen[stream] >= m_bufferPos[stream] + len)
  2113.        {
  2114. -        Sleep(1);
  2115. -        continue;
  2116. +        memcpy(m_pcmBuffer[stream]+m_bufferPos[stream], pcmPtr, len);
  2117. +        m_bufferPos[stream] += len;
  2118. +      }
  2119. +      else
  2120. +      {
  2121. +        CLog::Log(LOGDEBUG, "PAPlayer: Buffer full for audio packet output, dropped.");
  2122. +        m_bufferPos[stream] = 0;
  2123. +      }
  2124. +      int stuckcnt = 0;
  2125. +      while (m_bufferPos[stream] >= (int)m_pAudioDecoder[stream]->GetChunkLen())
  2126. +      {
  2127. +        int rtn = m_pAudioDecoder[stream]->AddPackets(m_pcmBuffer[stream], m_bufferPos[stream]);
  2128. +        if( rtn == 0 ) //no pcm data added
  2129. +        {
  2130. +          Sleep(1);
  2131. +          if (stuckcnt++ > 50)
  2132. +            break;
  2133. +        }
  2134. +        else
  2135. +        {
  2136. +          stuckcnt = 0;
  2137. +        }
  2138. +        m_bufferPos[stream] -= rtn;
  2139. +        memmove(m_pcmBuffer[stream], m_pcmBuffer[stream] + rtn, m_bufferPos[stream]);
  2140. +      }
  2141. +    }
  2142. +    if (m_pAudioDecoder2[stream])
  2143. +    {
  2144. +      if ((int)m_pcmBufLen2[stream] >= m_bufferPos2[stream] + len)
  2145. +      {
  2146. +        memcpy(m_pcmBuffer2[stream]+m_bufferPos2[stream], pcmPtr, len);
  2147. +        m_bufferPos2[stream] += len;
  2148. +      }
  2149. +      else
  2150. +      {
  2151. +        CLog::Log(LOGDEBUG, "PAPlayer: Buffer full for 2nd audio packet output, dropped.");
  2152. +        m_bufferPos2[stream] = 0;
  2153. +      }
  2154. +      int stuckcnt = 0;
  2155. +      while (m_bufferPos2[stream] >= (int)m_pAudioDecoder2[stream]->GetChunkLen())
  2156. +      {
  2157. +        int rtn = m_pAudioDecoder2[stream]->AddPackets(m_pcmBuffer2[stream], m_bufferPos2[stream]);
  2158. +        if( rtn == 0 ) //no pcm data added
  2159. +        {
  2160. +          Sleep(1);
  2161. +          if (stuckcnt++ > 50)
  2162. +            break;
  2163. +        }
  2164. +        else
  2165. +        {
  2166. +          stuckcnt = 0;
  2167. +        }
  2168. +        m_bufferPos2[stream] -= rtn;
  2169. +        memmove(m_pcmBuffer2[stream], m_pcmBuffer2[stream] + rtn, m_bufferPos2[stream]);
  2170.        }
  2171. -
  2172. -      m_bufferPos[stream] -= rtn;
  2173. -      memmove(m_pcmBuffer[stream], m_pcmBuffer[stream] + rtn, m_bufferPos[stream]);
  2174.      }
  2175.  
  2176.      // something done
  2177. @@ -1101,4 +1335,8 @@
  2178.    {
  2179.      m_pAudioDecoder[m_currentStream]->WaitCompletion();
  2180.    }
  2181. +  if (m_pAudioDecoder2[m_currentStream])
  2182. +  {
  2183. +    m_pAudioDecoder2[m_currentStream]->WaitCompletion();
  2184. +  }
  2185.  }
  2186. diff -Naur xbmc-10.1-Dharma/xbmc/cores/paplayer/PAPlayer.h xbmc-10.1-Dharma.patch/xbmc/cores/paplayer/PAPlayer.h
  2187. --- xbmc-10.1-Dharma/xbmc/cores/paplayer/PAPlayer.h 2011-10-31 13:42:33.220568236 +0000
  2188. +++ xbmc-10.1-Dharma.patch/xbmc/cores/paplayer/PAPlayer.h   2011-10-31 13:41:06.912214441 +0000
  2189. @@ -141,8 +141,10 @@
  2190.    bool AddPacketsToStream(int stream, CAudioDecoder &dec);
  2191.    bool FindFreePacket(int stream, DWORD *pdwPacket );     // Looks for a free packet
  2192.    void FreeStream(int stream);
  2193. +  void FreeStreamRenderer(int stream, bool bAudio2);
  2194.  #if defined(_LINUX) || defined(_WIN32)
  2195.    void DrainStream(int stream);
  2196. +  void DrainStream(int stream, bool bAudio2);
  2197.  #endif
  2198.    bool CreateStream(int stream, unsigned int channels, unsigned int samplerate, unsigned int bitspersample, CStdString codec = "");
  2199.    void FlushStreams();
  2200. @@ -158,9 +160,17 @@
  2201.    IAudioRenderer*   m_pAudioDecoder[2];
  2202.    float             m_latency[2];
  2203.    unsigned char*    m_pcmBuffer[2];
  2204. +  unsigned int      m_pcmBufLen[2];
  2205.    int               m_bufferPos[2];
  2206.    unsigned int      m_Chunklen[2];
  2207.  
  2208. +  IAudioRenderer*   m_pAudioDecoder2[2];
  2209. +  float             m_latency2[2];
  2210. +  unsigned char*    m_pcmBuffer2[2];
  2211. +  unsigned int      m_pcmBufLen2[2];
  2212. +  int               m_bufferPos2[2];
  2213. +  unsigned int      m_Chunklen2[2];
  2214. +
  2215.    unsigned int     m_SampleRate;
  2216.    unsigned int     m_Channels;
  2217.    unsigned int     m_BitsPerSample;
  2218. diff -Naur xbmc-10.1-Dharma/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp xbmc-10.1-Dharma.patch/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp
  2219. --- xbmc-10.1-Dharma/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp 2011-10-31 13:42:36.559814056 +0000
  2220. +++ xbmc-10.1-Dharma.patch/xbmc/cores/playercorefactory/PlayerCoreFactory.cpp   2011-10-31 13:41:01.354805310 +0000
  2221. @@ -161,7 +161,7 @@
  2222.  
  2223.      if (bAdd)
  2224.      {
  2225. -      if( g_guiSettings.GetInt("audiooutput.mode") == AUDIO_ANALOG )
  2226. +      if( g_guiSettings.GetInt("audiooutput.mode") == AUDIO_ANALOG && !AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput2.mode")) )
  2227.        {
  2228.          CLog::Log(LOGDEBUG, "CPlayerCoreFactory::GetPlayers: adding PAPlayer (%d)", EPC_PAPLAYER);
  2229.          vecCores.push_back(EPC_PAPLAYER);
  2230. diff -Naur xbmc-10.1-Dharma/xbmc/GUISettings.cpp xbmc-10.1-Dharma.patch/xbmc/GUISettings.cpp
  2231. --- xbmc-10.1-Dharma/xbmc/GUISettings.cpp   2011-10-31 13:42:26.116045231 +0000
  2232. +++ xbmc-10.1-Dharma.patch/xbmc/GUISettings.cpp 2011-10-31 13:41:01.415809799 +0000
  2233. @@ -453,6 +453,46 @@
  2234.    AddString(ao, "audiooutput.audiodevice", 545, "Default", SPIN_CONTROL_TEXT);
  2235.  #endif
  2236.  
  2237. +#if defined(_LINUX)
  2238. +  AddSeparator(ao, "audiooutput.sep2");
  2239. +#else
  2240. +  AddSeparator(ao, "audiooutput.sep1");
  2241. +#endif
  2242. +
  2243. +   map<int,int> audiomode2;
  2244. +   audiomode2.insert(make_pair(13106,AUDIO_NONE));
  2245. +   audiomode2.insert(make_pair(338,AUDIO_ANALOG));
  2246. +   audiomode2.insert(make_pair(339,AUDIO_IEC958));
  2247. +   audiomode2.insert(make_pair(420,AUDIO_HDMI  ));
  2248. +   AddInt(ao, "audiooutput2.mode", 337, AUDIO_NONE, audiomode2, SPIN_CONTROL_TEXT);
  2249. +  
  2250. +   map<int,int> channelLayout2;
  2251. +   for(int layout2 = 0; layout2 < PCM_MAX_LAYOUT; ++layout2)
  2252. +     channelLayout2.insert(make_pair(34101+layout2, layout2));
  2253. +   AddInt(ao, "audiooutput2.channellayout", 34100, PCM_LAYOUT_2_0, channelLayout2, SPIN_CONTROL_TEXT);
  2254. +   AddBool(ao, "audiooutput2.dontnormalizelevels", 346, true);
  2255. +  
  2256. +   AddBool(ao, "audiooutput2.ac3passthrough", 364, true);
  2257. +   AddBool(ao, "audiooutput2.dtspassthrough", 254, true);
  2258. +   AddBool(NULL, "audiooutput2.passthroughaac", 299, false);
  2259. +   AddBool(NULL, "audiooutput2.passthroughmp1", 300, false);
  2260. +   AddBool(NULL, "audiooutput2.passthroughmp2", 301, false);
  2261. +   AddBool(NULL, "audiooutput2.passthroughmp3", 302, false);
  2262. +  
  2263. +#ifdef __APPLE__
  2264. +   AddString(ao, "audiooutput2.audiodevice", 545, "Default", SPIN_CONTROL_TEXT);
  2265. +#elif defined(_LINUX)
  2266. +   AddSeparator(ao, "audiooutput2.sep3");
  2267. +   AddString(ao, "audiooutput2.audiodevice", 545, "default", SPIN_CONTROL_TEXT);
  2268. +   AddString(ao, "audiooutput2.customdevice", 1300, "", EDIT_CONTROL_INPUT);
  2269. +   AddSeparator(ao, "audiooutput2.sep4");
  2270. +   AddString(ao, "audiooutput2.passthroughdevice", 546, "iec958", SPIN_CONTROL_TEXT);
  2271. +   AddString(ao, "audiooutput2.custompassthrough", 1301, "", EDIT_CONTROL_INPUT);
  2272. +   AddSeparator(ao, "audiooutput2.sep5");
  2273. +#elif defined(_WIN32)
  2274. +   AddString(ao, "audiooutput2.audiodevice", 545, "Default", SPIN_CONTROL_TEXT);
  2275. +#endif
  2276. +
  2277.    CSettingsCategory* in = AddCategory(4, "input", 14094);
  2278.  #ifdef __APPLE__
  2279.    map<int,int> remotemode;
  2280. diff -Naur xbmc-10.1-Dharma/xbmc/GUISettings.h xbmc-10.1-Dharma.patch/xbmc/GUISettings.h
  2281. --- xbmc-10.1-Dharma/xbmc/GUISettings.h 2011-10-31 13:42:26.118045376 +0000
  2282. +++ xbmc-10.1-Dharma.patch/xbmc/GUISettings.h   2011-10-31 13:41:06.929215692 +0000
  2283. @@ -79,6 +79,7 @@
  2284.  #define CDDARIP_QUALITY_STANDARD 2
  2285.  #define CDDARIP_QUALITY_EXTREME  3
  2286.  
  2287. +#define AUDIO_NONE        0xF
  2288.  #define AUDIO_ANALOG      0
  2289.  #define AUDIO_IEC958      1
  2290.  #define AUDIO_HDMI        2
  2291. diff -Naur xbmc-10.1-Dharma/xbmc/GUIWindowSettingsCategory.cpp xbmc-10.1-Dharma.patch/xbmc/GUIWindowSettingsCategory.cpp
  2292. --- xbmc-10.1-Dharma/xbmc/GUIWindowSettingsCategory.cpp 2011-10-31 13:42:26.171049280 +0000
  2293. +++ xbmc-10.1-Dharma.patch/xbmc/GUIWindowSettingsCategory.cpp   2011-10-31 13:41:01.490815323 +0000
  2294. @@ -583,6 +583,14 @@
  2295.      {
  2296.        FillInAudioDevices(pSetting,true);
  2297.      }
  2298. +    else if (strSetting.Equals("audiooutput2.audiodevice"))
  2299. +    {
  2300. +      FillInAudioDevices(pSetting,false,true);
  2301. +    }
  2302. +    else if (strSetting.Equals("audiooutput2.passthroughdevice"))
  2303. +    {
  2304. +      FillInAudioDevices(pSetting,true,true);
  2305. +    }
  2306.      else if (strSetting.Equals("videoplayer.synctype"))
  2307.      {
  2308.        CSettingInt *pSettingInt = (CSettingInt*)pSetting;
  2309. @@ -796,6 +804,26 @@
  2310.        CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
  2311.        if (pControl) pControl->SetEnabled(AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput.mode")));
  2312.      }
  2313. +    else if (
  2314. +             strSetting.Equals("audiooutput2.channellayout") ||
  2315. +             strSetting.Equals("audiooutput2.dontnormalizelevels") ||
  2316. +             strSetting.Equals("audiooutput2.audiodevice"))
  2317. +    { // only visible if audioouput2 is used
  2318. +      CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
  2319. +      if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("audiooutput2.mode") != AUDIO_NONE);
  2320. +    }
  2321. +    else if (
  2322. +             strSetting.Equals("audiooutput2.passthroughdevice") ||
  2323. +             strSetting.Equals("audiooutput2.ac3passthrough") ||
  2324. +             strSetting.Equals("audiooutput2.dtspassthrough") ||
  2325. +             strSetting.Equals("audiooutput2.passthroughaac") ||
  2326. +             strSetting.Equals("audiooutput2.passthroughmp1") ||
  2327. +             strSetting.Equals("audiooutput2.passthroughmp2") ||
  2328. +             strSetting.Equals("audiooutput2.passthroughmp3"))
  2329. +    { // only visible if we are in digital mode
  2330. +      CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
  2331. +      if (pControl) pControl->SetEnabled(AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput2.mode")));
  2332. +    }
  2333.      else if (strSetting.Equals("musicplayer.crossfade"))
  2334.      {
  2335.        CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
  2336. @@ -1023,6 +1051,23 @@
  2337.        CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
  2338.        if (pControl) pControl->SetEnabled(g_guiSettings.GetString("audiooutput.audiodevice").Equals("custom"));
  2339.      }
  2340. +    else if (strSetting.Equals("audiooutput2.custompassthrough"))
  2341. +    {
  2342. +      CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
  2343. +      if (AUDIO_IS_BITSTREAM(g_guiSettings.GetInt("audiooutput2.mode")))
  2344. +      {
  2345. +        if (pControl) pControl->SetEnabled(g_guiSettings.GetString("audiooutput2.passthroughdevice").Equals("custom"));
  2346. +      }
  2347. +      else
  2348. +      {
  2349. +        if (pControl) pControl->SetEnabled(false);
  2350. +      }
  2351. +    }
  2352. +    else if (strSetting.Equals("audiooutput2.customdevice"))
  2353. +    {
  2354. +      CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
  2355. +      if (pControl) pControl->SetEnabled(g_guiSettings.GetInt("audiooutput2.mode") != AUDIO_NONE && g_guiSettings.GetString("audiooutput2.audiodevice").Equals("custom"));
  2356. +    }
  2357.  #endif
  2358.    }
  2359.  }
  2360. @@ -1294,6 +1339,26 @@
  2361.  #endif
  2362.    }
  2363.  #endif
  2364. +  else if (strSetting.Equals("audiooutput2.audiodevice"))
  2365. +  {
  2366. +      CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID());
  2367. +#if !defined(__APPLE__)
  2368. +      g_guiSettings.SetString("audiooutput2.audiodevice", m_AnalogAudioSinkMap[pControl->GetCurrentLabel()]);
  2369. +#else
  2370. +      g_guiSettings.SetString("audiooutput2.audiodevice", pControl->GetCurrentLabel());
  2371. +#endif
  2372. +  }
  2373. +#if defined(_LINUX)
  2374. +  else if (strSetting.Equals("audiooutput2.passthroughdevice"))
  2375. +  {
  2376. +    CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID());
  2377. +#if defined(_LINUX) && !defined(__APPLE__)
  2378. +      g_guiSettings.SetString("audiooutput2.passthroughdevice", m_DigitalAudioSinkMap[pControl->GetCurrentLabel()]);
  2379. +#else
  2380. +      g_guiSettings.SetString("audiooutput2.passthroughdevice", pControl->GetCurrentLabel());
  2381. +#endif
  2382. +  }
  2383. +#endif
  2384.  #ifdef HAS_LCD
  2385.    else if (strSetting.Equals("videoscreen.haslcd"))
  2386.    {
  2387. @@ -2776,7 +2841,7 @@
  2388.    }
  2389.  }
  2390.  
  2391. -void CGUIWindowSettingsCategory::FillInAudioDevices(CSetting* pSetting, bool Passthrough)
  2392. +void CGUIWindowSettingsCategory::FillInAudioDevices(CSetting* pSetting, bool Passthrough, bool bAudio2)
  2393.  {
  2394.  #ifdef __APPLE__
  2395.    if (Passthrough)
  2396. @@ -2797,8 +2862,16 @@
  2397.      CCoreAudioDevice device(deviceList.front());
  2398.      pControl->AddLabel(device.GetName(deviceName), i);
  2399.  
  2400. -    if (g_guiSettings.GetString("audiooutput.audiodevice").Equals(deviceName))
  2401. -      activeDevice = i; // Tag this one
  2402. +    if(!bAudio2)
  2403. +    {
  2404. +      if (g_guiSettings.GetString("audiooutput.audiodevice").Equals(deviceName))
  2405. +        activeDevice = i; // Tag this one
  2406. +   }
  2407. +    else
  2408. +    {
  2409. +      if (g_guiSettings.GetString("audiooutput2.audiodevice").Equals(deviceName))
  2410. +        activeDevice = i; // Tag this one
  2411. +    }
  2412.  
  2413.      deviceList.pop_front();
  2414.    }
  2415. @@ -2807,7 +2880,15 @@
  2416.    CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID());
  2417.    pControl->Clear();
  2418.  
  2419. -  CStdString currentDevice = Passthrough ? g_guiSettings.GetString("audiooutput.passthroughdevice") : g_guiSettings.GetString("audiooutput.audiodevice");
  2420. +  CStdString currentDevice;
  2421. +  if(!bAudio2)
  2422. +  {
  2423. +    currentDevice = Passthrough ? g_guiSettings.GetString("audiooutput.passthroughdevice") : g_guiSettings.GetString("audiooutput.audiodevice");
  2424. +  }
  2425. +  else
  2426. +  {
  2427. +    currentDevice = Passthrough ? g_guiSettings.GetString("audiooutput2.passthroughdevice") : g_guiSettings.GetString("audiooutput2.audiodevice");
  2428. +  }
  2429.  
  2430.    if (Passthrough)
  2431.    {
  2432. diff -Naur xbmc-10.1-Dharma/xbmc/GUIWindowSettingsCategory.h xbmc-10.1-Dharma.patch/xbmc/GUIWindowSettingsCategory.h
  2433. --- xbmc-10.1-Dharma/xbmc/GUIWindowSettingsCategory.h   2011-10-31 13:42:26.172049356 +0000
  2434. +++ xbmc-10.1-Dharma.patch/xbmc/GUIWindowSettingsCategory.h 2011-10-31 13:41:06.942216650 +0000
  2435. @@ -63,7 +63,7 @@
  2436.    void FillInNetworkInterfaces(CSetting *pSetting);
  2437.    void NetworkInterfaceChanged(void);
  2438.  
  2439. -  void FillInAudioDevices(CSetting* pSetting, bool Passthrough = false);
  2440. +  void FillInAudioDevices(CSetting* pSetting, bool Passthrough = false, bool bAudio2 = false);
  2441.  
  2442.    virtual void SetupControls();
  2443.    void CreateSettings();
  2444. diff -Naur xbmc-10.1-Dharma/xbmc/LangCodeExpander.cpp xbmc-10.1-Dharma.patch/xbmc/LangCodeExpander.cpp
  2445. --- xbmc-10.1-Dharma/xbmc/LangCodeExpander.cpp  2011-10-31 13:42:26.218052740 +0000
  2446. +++ xbmc-10.1-Dharma.patch/xbmc/LangCodeExpander.cpp    2011-10-31 13:41:01.528818120 +0000
  2447. @@ -22,8 +22,13 @@
  2448.  #include "LangCodeExpander.h"
  2449.  #include "SectionLoader.h"
  2450.  #include "tinyXML/tinyxml.h"
  2451. +#include "utils/log.h"
  2452. +
  2453. +#define MAKECODE(a, b, c, d)  ((((long)(a))<<24) | (((long)(b))<<16) | (((long)(c))<<8) | (long)(d))
  2454. +#define MAKETWOCHARCODE(a, b) ((((long)(a))<<8) | (long)(b))
  2455. +
  2456. +CLangCodeExpander  g_LangCodeExpander;
  2457.  
  2458. -#define MAKECODE(a, b, c, d) ((((long)(a))<<24) | (((long)(b))<<16) | (((long)(c))<<8) | (long)(d))
  2459.  typedef struct LCENTRY
  2460.  {
  2461.    long code;
  2462. @@ -33,8 +38,22 @@
  2463.  extern const struct LCENTRY g_iso639_1[143];
  2464.  extern const struct LCENTRY g_iso639_2[536];
  2465.  
  2466. +struct CharCodeConvertionWithHack
  2467. +{
  2468. +  const char* old;
  2469. +  const char* id;
  2470. +  const char* win_id;
  2471. +};
  2472.  
  2473. -CLangCodeExpander g_LangCodeExpander;
  2474. +struct CharCodeConvertion
  2475. +{
  2476. +  const char* old;
  2477. +  const char* id;
  2478. +};
  2479. +
  2480. +// declared as extern to allow forward declaration
  2481. +extern const CharCodeConvertionWithHack CharCode2To3[184];
  2482. +extern const CharCodeConvertion RegionCode2To3[246];
  2483.  
  2484.  CLangCodeExpander::CLangCodeExpander(void)
  2485.  {}
  2486. @@ -125,6 +144,61 @@
  2487.    return Lookup(desc, lang);
  2488.  }
  2489.  
  2490. +#ifdef _WIN32
  2491. +bool CLangCodeExpander::ConvertTwoToThreeCharCode(CStdString& strThreeCharCode, const CStdString& strTwoCharCode, bool localeHack /*= false*/)
  2492. +#else
  2493. +bool CLangCodeExpander::ConvertTwoToThreeCharCode(CStdString& strThreeCharCode, const CStdString& strTwoCharCode)
  2494. +#endif
  2495. +{      
  2496. +  if ( strTwoCharCode.length() == 2 )
  2497. +  {
  2498. +    CStdString strTwoCharCodeLower( strTwoCharCode );
  2499. +    strTwoCharCodeLower.MakeLower();
  2500. +    strTwoCharCodeLower.TrimLeft();
  2501. +    strTwoCharCodeLower.TrimRight();
  2502. +
  2503. +    for (unsigned int index = 0; index < sizeof(CharCode2To3) / sizeof(CharCode2To3[0]); ++index)
  2504. +    {
  2505. +      if (strTwoCharCodeLower.Equals(CharCode2To3[index].old))
  2506. +      {
  2507. +#ifdef _WIN32
  2508. +        if (localeHack && CharCode2To3[index].win_id)
  2509. +        {
  2510. +          strThreeCharCode = CharCode2To3[index].win_id;
  2511. +          return true;
  2512. +        }
  2513. +#endif
  2514. +        strThreeCharCode = CharCode2To3[index].id;
  2515. +        return true;
  2516. +      }
  2517. +    }
  2518. +  }
  2519. +
  2520. +  // not a 2 char code
  2521. +  return false;
  2522. +}
  2523. +
  2524. +bool CLangCodeExpander::ConvertLinuxToWindowsRegionCodes(const CStdString& strTwoCharCode, CStdString& strThreeCharCode)
  2525. +{
  2526. +  if (strTwoCharCode.length() != 2)
  2527. +    return false;
  2528. +
  2529. +  CStdString strLower( strTwoCharCode );
  2530. +  strLower.MakeLower();
  2531. +  strLower.TrimLeft();
  2532. +  strLower.TrimRight();
  2533. +  for (unsigned int index = 0; index < sizeof(RegionCode2To3) / sizeof(RegionCode2To3[0]); ++index)
  2534. +  {
  2535. +    if (strLower.Equals(RegionCode2To3[index].old))
  2536. +    {
  2537. +      strThreeCharCode = RegionCode2To3[index].id;
  2538. +      return true;
  2539. +    }
  2540. +  }
  2541. +
  2542. +  return true;
  2543. +}
  2544. +
  2545.  bool CLangCodeExpander::LookupInMap(CStdString& desc, const CStdString& code)
  2546.  {
  2547.    STRINGLOOKUPTABLE::iterator it;
  2548. @@ -869,3 +943,442 @@
  2549.    { MAKECODE('\0','z','u','l'), "Zulu" },
  2550.    { MAKECODE('\0','z','u','n'), "Zuni" },
  2551.  };
  2552. +
  2553. +const CharCodeConvertionWithHack CharCode2To3[184] =
  2554. +{
  2555. +  { "aa", "aar", NULL },
  2556. +  { "ab", "abk", NULL },
  2557. +  { "af", "afr", NULL },
  2558. +  { "ak", "aka", NULL },
  2559. +  { "am", "amh", NULL },
  2560. +  { "ar", "ara", NULL },
  2561. +  { "an", "arg", NULL },
  2562. +  { "as", "asm", NULL },
  2563. +  { "av", "ava", NULL },
  2564. +  { "ae", "ave", NULL },
  2565. +  { "ay", "aym", NULL },
  2566. +  { "az", "aze", NULL },
  2567. +  { "ba", "bak", NULL },
  2568. +  { "bm", "bam", NULL },
  2569. +  { "be", "bel", NULL },
  2570. +  { "bn", "ben", NULL },
  2571. +  { "bh", "bih", NULL },
  2572. +  { "bi", "bis", NULL },
  2573. +  { "bo", "tib", NULL },
  2574. +  { "bs", "bos", NULL },
  2575. +  { "br", "bre", NULL },
  2576. +  { "bg", "bul", NULL },
  2577. +  { "ca", "cat", NULL },
  2578. +  { "cs", "cze", "csy" },
  2579. +  { "ch", "cha", NULL },
  2580. +  { "ce", "che", NULL },
  2581. +  { "cu", "chu", NULL },
  2582. +  { "cv", "chv", NULL },
  2583. +  { "kw", "cor", NULL },
  2584. +  { "co", "cos", NULL },
  2585. +  { "cr", "cre", NULL },
  2586. +  { "cy", "wel", NULL },
  2587. +  { "da", "dan", NULL },
  2588. +  { "de", "ger", "deu" },
  2589. +  { "dv", "div", NULL },
  2590. +  { "dz", "dzo", NULL },
  2591. +  { "el", "gre", "ell" },
  2592. +  { "en", "eng", NULL },
  2593. +  { "eo", "epo", NULL },
  2594. +  { "et", "est", NULL },
  2595. +  { "eu", "baq", NULL },
  2596. +  { "ee", "ewe", NULL },
  2597. +  { "fo", "fao", NULL },
  2598. +  { "fa", "per", NULL },
  2599. +  { "fj", "fij", NULL },
  2600. +  { "fi", "fin", NULL },
  2601. +  { "fr", "fre", "fra" },
  2602. +  { "fy", "fry", NULL },
  2603. +  { "ff", "ful", NULL },
  2604. +  { "gd", "gla", NULL },
  2605. +  { "ga", "gle", NULL },
  2606. +  { "gl", "glg", NULL },
  2607. +  { "gv", "glv", NULL },
  2608. +  { "gn", "grn", NULL },
  2609. +  { "gu", "guj", NULL },
  2610. +  { "ht", "hat", NULL },
  2611. +  { "ha", "hau", NULL },
  2612. +  { "he", "heb", NULL },
  2613. +  { "hz", "her", NULL },
  2614. +  { "hi", "hin", NULL },
  2615. +  { "ho", "hmo", NULL },
  2616. +  { "hr", "hrv", NULL },
  2617. +  { "hu", "hun", NULL },
  2618. +  { "hy", "arm", NULL },
  2619. +  { "ig", "ibo", NULL },
  2620. +  { "io", "ido", NULL },
  2621. +  { "ii", "iii", NULL },
  2622. +  { "iu", "iku", NULL },
  2623. +  { "ie", "ile", NULL },
  2624. +  { "ia", "ina", NULL },
  2625. +  { "id", "ind", NULL },
  2626. +  { "ik", "ipk", NULL },
  2627. +  { "is", "ice", "isl" },
  2628. +  { "it", "ita", NULL },
  2629. +  { "jv", "jav", NULL },
  2630. +  { "ja", "jpn", NULL },
  2631. +  { "kl", "kal", NULL },
  2632. +  { "kn", "kan", NULL },
  2633. +  { "ks", "kas", NULL },
  2634. +  { "ka", "geo", NULL },
  2635. +  { "kr", "kau", NULL },
  2636. +  { "kk", "kaz", NULL },
  2637. +  { "km", "khm", NULL },
  2638. +  { "ki", "kik", NULL },
  2639. +  { "rw", "kin", NULL },
  2640. +  { "ky", "kir", NULL },
  2641. +  { "kv", "kom", NULL },
  2642. +  { "kg", "kon", NULL },
  2643. +  { "ko", "kor", NULL },
  2644. +  { "kj", "kua", NULL },
  2645. +  { "ku", "kur", NULL },
  2646. +  { "lo", "lao", NULL },
  2647. +  { "la", "lat", NULL },
  2648. +  { "lv", "lav", NULL },
  2649. +  { "li", "lim", NULL },
  2650. +  { "ln", "lin", NULL },
  2651. +  { "lt", "lit", NULL },
  2652. +  { "lb", "ltz", NULL },
  2653. +  { "lu", "lub", NULL },
  2654. +  { "lg", "lug", NULL },
  2655. +  { "mk", "mac", NULL },
  2656. +  { "mh", "mah", NULL },
  2657. +  { "ml", "mal", NULL },
  2658. +  { "mi", "mao", NULL },
  2659. +  { "mr", "mar", NULL },
  2660. +  { "ms", "may", NULL },
  2661. +  { "mg", "mlg", NULL },
  2662. +  { "mt", "mlt", NULL },
  2663. +  { "mn", "mon", NULL },
  2664. +  { "my", "bur", NULL },
  2665. +  { "na", "nau", NULL },
  2666. +  { "nv", "nav", NULL },
  2667. +  { "nr", "nbl", NULL },
  2668. +  { "nd", "nde", NULL },
  2669. +  { "ng", "ndo", NULL },
  2670. +  { "ne", "nep", NULL },
  2671. +  { "nl", "dut", "nld" },
  2672. +  { "nn", "nno", NULL },
  2673. +  { "nb", "nob", NULL },
  2674. +  { "no", "nor", NULL },
  2675. +  { "ny", "nya", NULL },
  2676. +  { "oc", "oci", NULL },
  2677. +  { "oj", "oji", NULL },
  2678. +  { "or", "ori", NULL },
  2679. +  { "om", "orm", NULL },
  2680. +  { "os", "oss", NULL },
  2681. +  { "pa", "pan", NULL },
  2682. +  { "pi", "pli", NULL },
  2683. +  { "pl", "pol", "plk" },
  2684. +  { "pt", "por", "ptg" },
  2685. +  { "ps", "pus", NULL },
  2686. +  { "qu", "que", NULL },
  2687. +  { "rm", "roh", NULL },
  2688. +  { "ro", "rum", "ron" },
  2689. +  { "rn", "run", NULL },
  2690. +  { "ru", "rus", NULL },
  2691. +  { "sg", "sag", NULL },
  2692. +  { "sa", "san", NULL },
  2693. +  { "si", "sin", NULL },
  2694. +  { "sk", "slo", "sky" },
  2695. +  { "sl", "slv", NULL },
  2696. +  { "se", "sme", NULL },
  2697. +  { "sm", "smo", NULL },
  2698. +  { "sn", "sna", NULL },
  2699. +  { "sd", "snd", NULL },
  2700. +  { "so", "som", NULL },
  2701. +  { "st", "sot", NULL },
  2702. +  { "es", "spa", "esp" },
  2703. +  { "sq", "alb", NULL },
  2704. +  { "sc", "srd", NULL },
  2705. +  { "sr", "srp", NULL },
  2706. +  { "ss", "ssw", NULL },
  2707. +  { "su", "sun", NULL },
  2708. +  { "sw", "swa", NULL },
  2709. +  { "sv", "swe", "sve" },
  2710. +  { "ty", "tah", NULL },
  2711. +  { "ta", "tam", NULL },
  2712. +  { "tt", "tat", NULL },
  2713. +  { "te", "tel", NULL },
  2714. +  { "tg", "tgk", NULL },
  2715. +  { "tl", "tgl", NULL },
  2716. +  { "th", "tha", NULL },
  2717. +  { "ti", "tir", NULL },
  2718. +  { "to", "ton", NULL },
  2719. +  { "tn", "tsn", NULL },
  2720. +  { "ts", "tso", NULL },
  2721. +  { "tk", "tuk", NULL },
  2722. +  { "tr", "tur", "trk" },
  2723. +  { "tw", "twi", NULL },
  2724. +  { "ug", "uig", NULL },
  2725. +  { "uk", "ukr", NULL },
  2726. +  { "ur", "urd", NULL },
  2727. +  { "uz", "uzb", NULL },
  2728. +  { "ve", "ven", NULL },
  2729. +  { "vi", "vie", NULL },
  2730. +  { "vo", "vol", NULL },
  2731. +  { "wa", "wln", NULL },
  2732. +  { "wo", "wol", NULL },
  2733. +  { "xh", "xho", NULL },
  2734. +  { "yi", "yid", NULL },
  2735. +  { "yo", "yor", NULL },
  2736. +  { "za", "zha", NULL },
  2737. +  { "zh", "chi", NULL },
  2738. +  { "zu", "zul", NULL }
  2739. +};
  2740. +
  2741. +// Based on ISO 3166
  2742. +const CharCodeConvertion RegionCode2To3[246] =
  2743. +{
  2744. +  { "af", "afg" },
  2745. +  { "ax", "ala" },
  2746. +  { "al", "alb" },
  2747. +  { "dz", "dza" },
  2748. +  { "as", "asm" },
  2749. +  { "ad", "and" },
  2750. +  { "ao", "ago" },
  2751. +  { "ai", "aia" },
  2752. +  { "aq", "ata" },
  2753. +  { "ag", "atg" },
  2754. +  { "ar", "arg" },
  2755. +  { "am", "arm" },
  2756. +  { "aw", "abw" },
  2757. +  { "au", "aus" },
  2758. +  { "at", "aut" },
  2759. +  { "az", "aze" },
  2760. +  { "bs", "bhs" },
  2761. +  { "bh", "bhr" },
  2762. +  { "bd", "bgd" },
  2763. +  { "bb", "brb" },
  2764. +  { "by", "blr" },
  2765. +  { "be", "bel" },
  2766. +  { "bz", "blz" },
  2767. +  { "bj", "ben" },
  2768. +  { "bm", "bmu" },
  2769. +  { "bt", "btn" },
  2770. +  { "bo", "bol" },
  2771. +  { "ba", "bih" },
  2772. +  { "bw", "bwa" },
  2773. +  { "bv", "bvt" },
  2774. +  { "br", "bra" },
  2775. +  { "io", "iot" },
  2776. +  { "bn", "brn" },
  2777. +  { "bg", "bgr" },
  2778. +  { "bf", "bfa" },
  2779. +  { "bi", "bdi" },
  2780. +  { "kh", "khm" },
  2781. +  { "cm", "cmr" },
  2782. +  { "ca", "can" },
  2783. +  { "cv", "cpv" },
  2784. +  { "ky", "cym" },
  2785. +  { "cf", "caf" },
  2786. +  { "td", "tcd" },
  2787. +  { "cl", "chl" },
  2788. +  { "cn", "chn" },
  2789. +  { "cx", "cxr" },
  2790. +  { "cc", "cck" },
  2791. +  { "co", "col" },
  2792. +  { "km", "com" },
  2793. +  { "cg", "cog" },
  2794. +  { "cd", "cod" },
  2795. +  { "ck", "cok" },
  2796. +  { "cr", "cri" },
  2797. +  { "ci", "civ" },
  2798. +  { "hr", "hrv" },
  2799. +  { "cu", "cub" },
  2800. +  { "cy", "cyp" },
  2801. +  { "cz", "cze" },
  2802. +  { "dk", "dnk" },
  2803. +  { "dj", "dji" },
  2804. +  { "dm", "dma" },
  2805. +  { "do", "dom" },
  2806. +  { "ec", "ecu" },
  2807. +  { "eg", "egy" },
  2808. +  { "sv", "slv" },
  2809. +  { "gq", "gnq" },
  2810. +  { "er", "eri" },
  2811. +  { "ee", "est" },
  2812. +  { "et", "eth" },
  2813. +  { "fk", "flk" },
  2814. +  { "fo", "fro" },
  2815. +  { "fj", "fji" },
  2816. +  { "fi", "fin" },
  2817. +  { "fr", "fra" },
  2818. +  { "gf", "guf" },
  2819. +  { "pf", "pyf" },
  2820. +  { "tf", "atf" },
  2821. +  { "ga", "gab" },
  2822. +  { "gm", "gmb" },
  2823. +  { "ge", "geo" },
  2824. +  { "de", "deu" },
  2825. +  { "gh", "gha" },
  2826. +  { "gi", "gib" },
  2827. +  { "gr", "grc" },
  2828. +  { "gl", "grl" },
  2829. +  { "gd", "grd" },
  2830. +  { "gp", "glp" },
  2831. +  { "gu", "gum" },
  2832. +  { "gt", "gtm" },
  2833. +  { "gg", "ggy" },
  2834. +  { "gn", "gin" },
  2835. +  { "gw", "gnb" },
  2836. +  { "gy", "guy" },
  2837. +  { "ht", "hti" },
  2838. +  { "hm", "hmd" },
  2839. +  { "va", "vat" },
  2840. +  { "hn", "hnd" },
  2841. +  { "hk", "hkg" },
  2842. +  { "hu", "hun" },
  2843. +  { "is", "isl" },
  2844. +  { "in", "ind" },
  2845. +  { "id", "idn" },
  2846. +  { "ir", "irn" },
  2847. +  { "iq", "irq" },
  2848. +  { "ie", "irl" },
  2849. +  { "im", "imn" },
  2850. +  { "il", "isr" },
  2851. +  { "it", "ita" },
  2852. +  { "jm", "jam" },
  2853. +  { "jp", "jpn" },
  2854. +  { "je", "jey" },
  2855. +  { "jo", "jor" },
  2856. +  { "kz", "kaz" },
  2857. +  { "ke", "ken" },
  2858. +  { "ki", "kir" },
  2859. +  { "kp", "prk" },
  2860. +  { "kr", "kor" },
  2861. +  { "kw", "kwt" },
  2862. +  { "kg", "kgz" },
  2863. +  { "la", "lao" },
  2864. +  { "lv", "lva" },
  2865. +  { "lb", "lbn" },
  2866. +  { "ls", "lso" },
  2867. +  { "lr", "lbr" },
  2868. +  { "ly", "lby" },
  2869. +  { "li", "lie" },
  2870. +  { "lt", "ltu" },
  2871. +  { "lu", "lux" },
  2872. +  { "mo", "mac" },
  2873. +  { "mk", "mkd" },
  2874. +  { "mg", "mdg" },
  2875. +  { "mw", "mwi" },
  2876. +  { "my", "mys" },
  2877. +  { "mv", "mdv" },
  2878. +  { "ml", "mli" },
  2879. +  { "mt", "mlt" },
  2880. +  { "mh", "mhl" },
  2881. +  { "mq", "mtq" },
  2882. +  { "mr", "mrt" },
  2883. +  { "mu", "mus" },
  2884. +  { "yt", "myt" },
  2885. +  { "mx", "mex" },
  2886. +  { "fm", "fsm" },
  2887. +  { "md", "mda" },
  2888. +  { "mc", "mco" },
  2889. +  { "mn", "mng" },
  2890. +  { "me", "mne" },
  2891. +  { "ms", "msr" },
  2892. +  { "ma", "mar" },
  2893. +  { "mz", "moz" },
  2894. +  { "mm", "mmr" },
  2895. +  { "na", "nam" },
  2896. +  { "nr", "nru" },
  2897. +  { "np", "npl" },
  2898. +  { "nl", "nld" },
  2899. +  { "an", "ant" },
  2900. +  { "nc", "ncl" },
  2901. +  { "nz", "nzl" },
  2902. +  { "ni", "nic" },
  2903. +  { "ne", "ner" },
  2904. +  { "ng", "nga" },
  2905. +  { "nu", "niu" },
  2906. +  { "nf", "nfk" },
  2907. +  { "mp", "mnp" },
  2908. +  { "no", "nor" },
  2909. +  { "om", "omn" },
  2910. +  { "pk", "pak" },
  2911. +  { "pw", "plw" },
  2912. +  { "ps", "pse" },
  2913. +  { "pa", "pan" },
  2914. +  { "pg", "png" },
  2915. +  { "py", "pry" },
  2916. +  { "pe", "per" },
  2917. +  { "ph", "phl" },
  2918. +  { "pn", "pcn" },
  2919. +  { "pl", "pol" },
  2920. +  { "pt", "prt" },
  2921. +  { "pr", "pri" },
  2922. +  { "qa", "qat" },
  2923. +  { "re", "reu" },
  2924. +  { "ro", "rou" },
  2925. +  { "ru", "rus" },
  2926. +  { "rw", "rwa" },
  2927. +  { "bl", "blm" },
  2928. +  { "sh", "shn" },
  2929. +  { "kn", "kna" },
  2930. +  { "lc", "lca" },
  2931. +  { "mf", "maf" },
  2932. +  { "pm", "spm" },
  2933. +  { "vc", "vct" },
  2934. +  { "ws", "wsm" },
  2935. +  { "sm", "smr" },
  2936. +  { "st", "stp" },
  2937. +  { "sa", "sau" },
  2938. +  { "sn", "sen" },
  2939. +  { "rs", "srb" },
  2940. +  { "sc", "syc" },
  2941. +  { "sl", "sle" },
  2942. +  { "sg", "sgp" },
  2943. +  { "sk", "svk" },
  2944. +  { "si", "svn" },
  2945. +  { "sb", "slb" },
  2946. +  { "so", "som" },
  2947. +  { "za", "zaf" },
  2948. +  { "gs", "sgs" },
  2949. +  { "es", "esp" },
  2950. +  { "lk", "lka" },
  2951. +  { "sd", "sdn" },
  2952. +  { "sr", "sur" },
  2953. +  { "sj", "sjm" },
  2954. +  { "sz", "swz" },
  2955. +  { "se", "swe" },
  2956. +  { "ch", "che" },
  2957. +  { "sy", "syr" },
  2958. +  { "tw", "twn" },
  2959. +  { "tj", "tjk" },
  2960. +  { "tz", "tza" },
  2961. +  { "th", "tha" },
  2962. +  { "tl", "tls" },
  2963. +  { "tg", "tgo" },
  2964. +  { "tk", "tkl" },
  2965. +  { "to", "ton" },
  2966. +  { "tt", "tto" },
  2967. +  { "tn", "tun" },
  2968. +  { "tr", "tur" },
  2969. +  { "tm", "tkm" },
  2970. +  { "tc", "tca" },
  2971. +  { "tv", "tuv" },
  2972. +  { "ug", "uga" },
  2973. +  { "ua", "ukr" },
  2974. +  { "ae", "are" },
  2975. +  { "gb", "gbr" },
  2976. +  { "us", "usa" },
  2977. +  { "um", "umi" },
  2978. +  { "uy", "ury" },
  2979. +  { "uz", "uzb" },
  2980. +  { "vu", "vut" },
  2981. +  { "ve", "ven" },
  2982. +  { "vn", "vnm" },
  2983. +  { "vg", "vgb" },
  2984. +  { "vi", "vir" },
  2985. +  { "wf", "wlf" },
  2986. +  { "eh", "esh" },
  2987. +  { "ye", "yem" },
  2988. +  { "zm", "zmb" },
  2989. +  { "zw", "zwe" }
  2990. +};
  2991. diff -Naur xbmc-10.1-Dharma/xbmc/LangCodeExpander.h xbmc-10.1-Dharma.patch/xbmc/LangCodeExpander.h
  2992. --- xbmc-10.1-Dharma/xbmc/LangCodeExpander.h    2011-10-31 13:42:26.219052812 +0000
  2993. +++ xbmc-10.1-Dharma.patch/xbmc/LangCodeExpander.h  2011-10-31 13:41:06.957217754 +0000
  2994. @@ -34,6 +34,12 @@
  2995.  
  2996.    bool Lookup(CStdString& desc, const CStdString& code);
  2997.    bool Lookup(CStdString& desc, const int code);
  2998. +#ifdef _WIN32
  2999. +  bool ConvertTwoToThreeCharCode(CStdString& strThreeCharCode, const CStdString& strTwoCharCode, bool localeHack = false);
  3000. +#else
  3001. +  bool ConvertTwoToThreeCharCode(CStdString& strThreeCharCode, const CStdString& strTwoCharCode);
  3002. +#endif
  3003. +  bool ConvertLinuxToWindowsRegionCodes(const CStdString& strTwoCharCode, CStdString& strThreeCharCode);
  3004.  
  3005.    void LoadUserCodes(const TiXmlElement* pRootElement);
  3006.    void Clear();
  3007. diff -Naur xbmc-10.1-Dharma/xbmc/LangInfo.cpp xbmc-10.1-Dharma.patch/xbmc/LangInfo.cpp
  3008. --- xbmc-10.1-Dharma/xbmc/LangInfo.cpp  2011-10-31 13:42:26.220052885 +0000
  3009. +++ xbmc-10.1-Dharma.patch/xbmc/LangInfo.cpp    2011-10-31 13:41:01.548819592 +0000
  3010. @@ -20,6 +20,7 @@
  3011.   */
  3012.  
  3013.  #include "LangInfo.h"
  3014. +#include "LangCodeExpander.h"
  3015.  #include "AdvancedSettings.h"
  3016.  #include "GUISettings.h"
  3017.  #include "LocalizeStrings.h"
  3018. @@ -43,6 +44,8 @@
  3019.    m_strDVDMenuLanguage=region.m_strDVDMenuLanguage;
  3020.    m_strDVDAudioLanguage=region.m_strDVDAudioLanguage;
  3021.    m_strDVDSubtitleLanguage=region.m_strDVDSubtitleLanguage;
  3022. +  m_strLangLocaleName = region.m_strLangLocaleName;
  3023. +  m_strRegionLocaleName = region.m_strRegionLocaleName;
  3024.  
  3025.    m_strDateFormatShort=region.m_strDateFormatShort;
  3026.    m_strDateFormatLong=region.m_strDateFormatLong;
  3027. @@ -74,6 +77,7 @@
  3028.    m_strDVDMenuLanguage="en";
  3029.    m_strDVDAudioLanguage="en";
  3030.    m_strDVDSubtitleLanguage="en";
  3031. +  m_strLangLocaleName = "English";
  3032.  
  3033.    m_strDateFormatShort="DD/MM/YYYY";
  3034.    m_strDateFormatLong="DDDD, D MMMM YYYY";
  3035. @@ -136,6 +140,43 @@
  3036.    m_strTimeZone = strTimeZone;
  3037.  }
  3038.  
  3039. +// set the locale associated with this region global. This affects string
  3040. +// sorting & transformations
  3041. +void CLangInfo::CRegion::SetGlobalLocale()
  3042. +{
  3043. +  CStdString strLocale;
  3044. +  if (m_strRegionLocaleName.length() > 0)
  3045. +  {
  3046. +    strLocale = m_strLangLocaleName + "_" + m_strRegionLocaleName;
  3047. +#ifdef _LINUX
  3048. +    strLocale += ".UTF-8";
  3049. +#endif
  3050. +  }
  3051. +
  3052. +  CLog::Log(LOGDEBUG, "trying to set locale to %s", strLocale.c_str());
  3053. +
  3054. +  // We need to set the locale to only change the collate. Otherwise,
  3055. +  // decimal separator is changed depending of the current language
  3056. +  // (ie. "," in French or Dutch instead of "."). This breaks atof() and
  3057. +  // others similar functions.
  3058. +  locale current_locale = locale::classic(); // C-Locale
  3059. +  try
  3060. +  {
  3061. +    locale lcl = locale(strLocale);
  3062. +    strLocale = lcl.name();
  3063. +    current_locale = current_locale.combine< collate<wchar_t> >(lcl);
  3064. +
  3065. +    assert(use_facet< numpunct<char> >(current_locale).decimal_point() == '.');
  3066. +
  3067. +  } catch(...) {
  3068. +    current_locale = locale::classic();
  3069. +    strLocale = "C";
  3070. +  }
  3071. +
  3072. +  locale::global(current_locale);
  3073. +  CLog::Log(LOGINFO, "global locale set to %s", strLocale.c_str());
  3074. +}
  3075. +
  3076.  CLangInfo::CLangInfo()
  3077.  {
  3078.    SetDefaults();
  3079. @@ -164,6 +205,18 @@
  3080.      return false;
  3081.    }
  3082.  
  3083. +  if (pRootElement->Attribute("locale"))
  3084. +    m_defaultRegion.m_strLangLocaleName = pRootElement->Attribute("locale");
  3085. +
  3086. +#ifdef _WIN32
  3087. +  // Windows need 3 chars isolang code
  3088. +  if (m_defaultRegion.m_strLangLocaleName.length() == 2)
  3089. +  {
  3090. +    if (! g_LangCodeExpander.ConvertTwoToThreeCharCode(m_defaultRegion.m_strLangLocaleName, m_defaultRegion.m_strLangLocaleName, true))
  3091. +      m_defaultRegion.m_strLangLocaleName = "";
  3092. +  }
  3093. +#endif
  3094. +
  3095.    const TiXmlNode *pCharSets = pRootElement->FirstChild("charsets");
  3096.    if (pCharSets && !pCharSets->NoChildren())
  3097.    {
  3098. @@ -210,6 +263,18 @@
  3099.        if (region.m_strName.IsEmpty())
  3100.          region.m_strName="N/A";
  3101.  
  3102. +      if (pRegion->Attribute("locale"))
  3103. +        region.m_strRegionLocaleName = pRegion->Attribute("locale");
  3104. +
  3105. +#ifdef _WIN32
  3106. +      // Windows need 3 chars regions code
  3107. +      if (region.m_strRegionLocaleName.length() == 2)
  3108. +      {
  3109. +        if (! g_LangCodeExpander.ConvertLinuxToWindowsRegionCodes(region.m_strRegionLocaleName, region.m_strRegionLocaleName))
  3110. +          region.m_strRegionLocaleName = "";
  3111. +      }
  3112. +#endif
  3113. +
  3114.        const TiXmlNode *pDateLong=pRegion->FirstChild("datelong");
  3115.        if (pDateLong && !pDateLong->NoChildren())
  3116.          region.m_strDateFormatLong=pDateLong->FirstChild()->Value();
  3117. @@ -323,6 +388,16 @@
  3118.    return m_currentRegion->m_strDVDSubtitleLanguage;
  3119.  }
  3120.  
  3121. +const CStdString& CLangInfo::GetLanguageLocale() const
  3122. +{
  3123. +  return m_currentRegion->m_strLangLocaleName;
  3124. +}
  3125. +
  3126. +const CStdString& CLangInfo::GetRegionLocale() const
  3127. +{
  3128. +  return m_currentRegion->m_strRegionLocaleName;
  3129. +}
  3130. +
  3131.  // Returns the format string for the date of the current language
  3132.  const CStdString& CLangInfo::GetDateFormat(bool bLongDate/*=false*/) const
  3133.  {
  3134. @@ -372,6 +447,8 @@
  3135.      m_currentRegion=&m_regions.begin()->second;
  3136.    else
  3137.      m_currentRegion=&m_defaultRegion;
  3138. +
  3139. +  m_currentRegion->SetGlobalLocale();
  3140.  }
  3141.  
  3142.  // Returns the current region set for this language
  3143. diff -Naur xbmc-10.1-Dharma/xbmc/LangInfo.h xbmc-10.1-Dharma.patch/xbmc/LangInfo.h
  3144. --- xbmc-10.1-Dharma/xbmc/LangInfo.h    2011-10-31 13:42:26.221052960 +0000
  3145. +++ xbmc-10.1-Dharma.patch/xbmc/LangInfo.h  2011-10-31 13:41:06.981219521 +0000
  3146. @@ -42,6 +42,9 @@
  3147.    const CStdString& GetDVDSubtitleLanguage() const;
  3148.    const CStdString& GetTimeZone() const;
  3149.  
  3150. +  const CStdString& GetRegionLocale() const;
  3151. +  const CStdString& GetLanguageLocale() const;
  3152. +
  3153.    bool ForceUnicodeFont() const { return m_currentRegion->m_forceUnicodeFont; }
  3154.  
  3155.    const CStdString& GetDateFormat(bool bLongDate=false) const;
  3156. @@ -111,11 +114,14 @@
  3157.      void SetTempUnit(const CStdString& strUnit);
  3158.      void SetSpeedUnit(const CStdString& strUnit);
  3159.      void SetTimeZone(const CStdString& strTimeZone);
  3160. +    void SetGlobalLocale();
  3161.      CStdString m_strGuiCharSet;
  3162.      CStdString m_strSubtitleCharSet;
  3163.      CStdString m_strDVDMenuLanguage;
  3164.      CStdString m_strDVDAudioLanguage;
  3165.      CStdString m_strDVDSubtitleLanguage;
  3166. +    CStdString m_strLangLocaleName;
  3167. +    CStdString m_strRegionLocaleName;
  3168.      bool m_forceUnicodeFont;
  3169.      CStdString m_strName;
  3170.      CStdString m_strDateFormatLong;
  3171. diff -Naur xbmc-10.1-Dharma/xbmc/StringUtils.cpp xbmc-10.1-Dharma.patch/xbmc/StringUtils.cpp
  3172. --- xbmc-10.1-Dharma/xbmc/StringUtils.cpp   2011-10-31 13:42:26.349062385 +0000
  3173. +++ xbmc-10.1-Dharma.patch/xbmc/StringUtils.cpp 2011-10-31 13:41:01.596823125 +0000
  3174. @@ -32,6 +32,9 @@
  3175.  
  3176.  #include "StringUtils.h"
  3177.  #include "utils/RegExp.h"
  3178. +#include "utils/fstrcmp.h"
  3179. +#include "LangInfo.h"
  3180. +#include <locale>
  3181.  
  3182.  #include <math.h>
  3183.  #include <sstream>
  3184. @@ -133,31 +136,33 @@
  3185.  // Compares separately the numeric and alphabetic parts of a string.
  3186.  // returns negative if left < right, positive if left > right
  3187.  // and 0 if they are identical (essentially calculates left - right)
  3188. -int64_t StringUtils::AlphaNumericCompare(const char *left, const char *right)
  3189. +int64_t StringUtils::AlphaNumericCompare(const wchar_t *left, const wchar_t *right)
  3190.  {
  3191. -  unsigned char *l = (unsigned char *)left;
  3192. -  unsigned char *r = (unsigned char *)right;
  3193. -  unsigned char *ld, *rd;
  3194. -  unsigned char lc, rc;
  3195. +  wchar_t *l = (wchar_t *)left;
  3196. +  wchar_t *r = (wchar_t *)right;
  3197. +  wchar_t *ld, *rd;
  3198. +  wchar_t lc, rc;
  3199.    int64_t lnum, rnum;
  3200. +  const collate<wchar_t>& coll = use_facet< collate<wchar_t> >( locale() );
  3201. +  int cmp_res = 0;
  3202.    while (*l != 0 && *r != 0)
  3203.    {
  3204.      // check if we have a numerical value
  3205. -    if (*l >= '0' && *l <= '9' && *r >= '0' && *r <= '9')
  3206. +    if (*l >= L'0' && *l <= L'9' && *r >= L'0' && *r <= L'9')
  3207.      {
  3208.        ld = l;
  3209.        lnum = 0;
  3210. -      while (*ld >= '0' && *ld <= '9' && ld < l + 15)
  3211. +      while (*ld >= L'0' && *ld <= L'9' && ld < l + 15)
  3212.        { // compare only up to 15 digits
  3213.          lnum *= 10;
  3214.          lnum += *ld++ - '0';
  3215.        }
  3216.        rd = r;
  3217.        rnum = 0;
  3218. -      while (*rd >= '0' && *rd <= '9' && rd < r + 15)
  3219. +      while (*rd >= L'0' && *rd <= L'9' && rd < r + 15)
  3220.        { // compare only up to 15 digits
  3221.          rnum *= 10;
  3222. -        rnum += *rd++ - '0';
  3223. +        rnum += *rd++ - L'0';
  3224.        }
  3225.        // do we have numbers?
  3226.        if (lnum != rnum)
  3227. @@ -170,15 +175,16 @@
  3228.      }
  3229.      // do case less comparison
  3230.      lc = *l;
  3231. -    if (lc >= 'A' && lc <= 'Z')
  3232. -      lc += 'a'-'A';
  3233. +    if (lc >= L'A' && lc <= L'Z')
  3234. +      lc += L'a'-L'A';
  3235.      rc = *r;
  3236. -    if (rc >= 'A' && rc <= 'Z')
  3237. -      rc += 'a'-'A';
  3238. -    // ok, do a normal comparison.  Add special case stuff (eg '(' characters)) in here later
  3239. -    if (lc  != rc)
  3240. +    if (rc >= L'A' && rc <= L'Z')
  3241. +      rc += L'a'- L'A';
  3242. +
  3243. +    // ok, do a normal comparison, taking current locale into account. Add special case stuff (eg '(' characters)) in here later
  3244. +    if ((cmp_res = coll.compare(&lc, &lc + 1, &rc, &rc + 1)) != 0)
  3245.      {
  3246. -      return lc - rc;
  3247. +      return cmp_res;
  3248.      }
  3249.      l++; r++;
  3250.    }
  3251. @@ -412,3 +418,26 @@
  3252.    return (guidRE.RegFind(uuid.c_str()) == 0);
  3253.  }
  3254.  
  3255. +double StringUtils::CompareFuzzy(const CStdString &left, const CStdString &right)
  3256. +{
  3257. +  return (0.5 + fstrcmp(left.c_str(), right.c_str(), 0.0) * (left.length() + right.length())) / 2.0;
  3258. +}
  3259. +
  3260. +int StringUtils::FindBestMatch(const CStdString &str, const CStdStringArray &strings, double &matchscore)
  3261. +{
  3262. +  int best = -1;
  3263. +  matchscore = 0;
  3264. +
  3265. +  int i = 0;
  3266. +  for (CStdStringArray::const_iterator it = strings.begin(); it != strings.end(); it++, i++)
  3267. +  {
  3268. +    int maxlength = max(str.length(), it->length());
  3269. +    double score = StringUtils::CompareFuzzy(str, *it) / maxlength;
  3270. +    if (score > matchscore)
  3271. +    {
  3272. +      matchscore = score;
  3273. +      best = i;
  3274. +    }
  3275. +  }
  3276. +  return best;
  3277. +}
  3278. diff -Naur xbmc-10.1-Dharma/xbmc/StringUtils.h xbmc-10.1-Dharma.patch/xbmc/StringUtils.h
  3279. --- xbmc-10.1-Dharma/xbmc/StringUtils.h 2011-10-31 13:42:26.350062459 +0000
  3280. +++ xbmc-10.1-Dharma.patch/xbmc/StringUtils.h   2011-10-31 13:41:07.001220993 +0000
  3281. @@ -43,7 +43,7 @@
  3282.    static void JoinString(const CStdStringArray &strings, const CStdString& delimiter, CStdString& result);
  3283.    static int SplitString(const CStdString& input, const CStdString& delimiter, CStdStringArray &results, unsigned int iMaxStrings = 0);
  3284.    static int FindNumber(const CStdString& strInput, const CStdString &strFind);
  3285. -  static int64_t AlphaNumericCompare(const char *left, const char *right);
  3286. +  static int64_t AlphaNumericCompare(const wchar_t *left, const wchar_t *right);
  3287.    static long TimeStringToSeconds(const CStdString &timeString);
  3288.    static void RemoveCRLF(CStdString& strLine);
  3289.  
  3290. @@ -64,6 +64,8 @@
  3291.    static void WordToDigits(CStdString &word);
  3292.    static CStdString CreateUUID();
  3293.    static bool ValidateUUID(const CStdString &uuid); // NB only validates syntax
  3294. +  static double CompareFuzzy(const CStdString &left, const CStdString &right);
  3295. +  static int FindBestMatch(const CStdString &str, const CStdStringArray &strings, double &matchscore);
  3296.  private:
  3297.    static CStdString m_lastUUID;
  3298.  };
  3299. diff -Naur xbmc-10.1-Dharma/xbmc/SystemGlobals.h xbmc-10.1-Dharma.patch/xbmc/SystemGlobals.h
  3300. --- xbmc-10.1-Dharma/xbmc/SystemGlobals.h   2011-10-31 13:42:26.351062532 +0000
  3301. +++ xbmc-10.1-Dharma.patch/xbmc/SystemGlobals.h 2011-10-31 13:41:07.031223203 +0000
  3302. @@ -33,6 +33,7 @@
  3303.  struct CSystemGlobals
  3304.  {
  3305.    // Classes that must be initialized/destructed in a specific order because of dependencies.
  3306. +  CSystemGlobals() : m_audioContext2(true) {}
  3307.  
  3308.    CGUISettings m_guiSettings;
  3309.  
  3310. @@ -55,6 +56,7 @@
  3311.    CGUILargeTextureManager m_largeTextureManager;
  3312.    CXBMCRenderManager m_renderManager;
  3313.    CAudioContext      m_audioContext;
  3314. +  CAudioContext      m_audioContext2;
  3315.    CGraphicContext    m_graphicsContext;
  3316.    CMouseStat         m_Mouse;
  3317.    CApplication       m_application;
  3318. diff -Naur xbmc-10.1-Dharma/xbmc/utils/GUIInfoManager.cpp xbmc-10.1-Dharma.patch/xbmc/utils/GUIInfoManager.cpp
  3319. --- xbmc-10.1-Dharma/xbmc/utils/GUIInfoManager.cpp  2011-10-31 13:42:44.609406631 +0000
  3320. +++ xbmc-10.1-Dharma.patch/xbmc/utils/GUIInfoManager.cpp    2011-10-31 13:41:01.623825115 +0000
  3321. @@ -3965,8 +3965,8 @@
  3322.      break;
  3323.    case LISTITEM_SORT_LETTER:
  3324.      {
  3325. -      CStdString letter = g_charsetConverter.utf8Left(item->GetSortLabel(), 1);
  3326. -      letter.ToUpper();
  3327. +      CStdString letter;
  3328. +      g_charsetConverter.wToUTF8(item->GetSortLabel().Left(1).ToUpper(), letter);
  3329.        return letter;
  3330.      }
  3331.      break;
  3332. diff -Naur xbmc-10.1-Dharma/xbmc/utils/PCMRemap.cpp xbmc-10.1-Dharma.patch/xbmc/utils/PCMRemap.cpp
  3333. --- xbmc-10.1-Dharma/xbmc/utils/PCMRemap.cpp    2011-10-31 13:42:44.649409576 +0000
  3334. +++ xbmc-10.1-Dharma.patch/xbmc/utils/PCMRemap.cpp  2011-10-31 13:41:01.629825556 +0000
  3335. @@ -167,7 +167,8 @@
  3336.    m_ignoreLayout(false),
  3337.    m_inChannels  (0),
  3338.    m_outChannels (0),
  3339. -  m_inSampleSize(0)
  3340. +  m_inSampleSize(0),
  3341. +  m_bAudio2     (false)
  3342.  {
  3343.    Dispose();
  3344.  }
  3345. @@ -350,7 +351,11 @@
  3346.    m_outStride = m_inSampleSize * m_outChannels;
  3347.  
  3348.    /* see if we need to normalize the levels */
  3349. -  bool dontnormalize = g_guiSettings.GetBool("audiooutput.dontnormalizelevels");
  3350. +  bool dontnormalize;
  3351. +  if (!m_bAudio2)
  3352. +    dontnormalize = g_guiSettings.GetBool("audiooutput.dontnormalizelevels");
  3353. +  else
  3354. +    dontnormalize = g_guiSettings.GetBool("audiooutput2.dontnormalizelevels");
  3355.    CLog::Log(LOGDEBUG, "CPCMRemap: Downmix normalization is %s", (dontnormalize ? "disabled" : "enabled"));
  3356.  
  3357.    ResolveChannels();
  3358. @@ -444,7 +449,10 @@
  3359.    assert(sampleSize == 2);
  3360.  
  3361.    /* get the audio layout, and count the channels in it */
  3362. -  m_channelLayout  = (enum PCMLayout)g_guiSettings.GetInt("audiooutput.channellayout");
  3363. +  if (!m_bAudio2)
  3364. +    m_channelLayout  = (enum PCMLayout)g_guiSettings.GetInt("audiooutput.channellayout");
  3365. +  else
  3366. +    m_channelLayout  = (enum PCMLayout)g_guiSettings.GetInt("audiooutput2.channellayout");
  3367.    if (m_channelLayout >= PCM_MAX_LAYOUT) m_channelLayout = PCM_LAYOUT_2_0;
  3368.  
  3369.    CLog::Log(LOGINFO, "CPCMRemap: Configured speaker layout: %s\n", PCMLayoutStr(m_channelLayout).c_str());
  3370. diff -Naur xbmc-10.1-Dharma/xbmc/utils/PCMRemap.h xbmc-10.1-Dharma.patch/xbmc/utils/PCMRemap.h
  3371. --- xbmc-10.1-Dharma/xbmc/utils/PCMRemap.h  2011-10-31 13:42:44.650409650 +0000
  3372. +++ xbmc-10.1-Dharma.patch/xbmc/utils/PCMRemap.h    2011-10-31 13:41:07.061225411 +0000
  3373. @@ -90,6 +90,7 @@
  3374.    int                m_inStride, m_outStride;
  3375.    struct PCMMapInfo  m_lookupMap[PCM_MAX_CH + 1][PCM_MAX_CH + 1];
  3376.    int                m_counts[PCM_MAX_CH];
  3377. +  bool               m_bAudio2;
  3378.  
  3379.    struct PCMMapInfo* ResolveChannel(enum PCMChannels channel, float level, bool ifExists, std::vector<enum PCMChannels> path, struct PCMMapInfo *tablePtr);
  3380.    void               ResolveChannels(); //!< Partial BuildMap(), just enough to see which output channels are active
  3381. @@ -111,6 +112,7 @@
  3382.    int  InBytesToFrames (int bytes );
  3383.    int  FramesToOutBytes(int frames);
  3384.    int  FramesToInBytes (int frames);
  3385. +  void SetAudio2(bool bAudio2){ m_bAudio2 = bAudio2; };
  3386.  };
  3387.  
  3388.  #endif
  3389.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement