/*
* Copyright (C) 2010-2013 Team XBMC
- * http://www.xbmc.org
+ * http://xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <Functiondiscoverykeys_devpkey.h>
#include <Rpc.h>
#include "cores/AudioEngine/Utils/AEUtil.h"
+#include "utils/StringUtils.h"
#pragma comment(lib, "Rpcrt4.lib")
extern HWND g_hWnd;
LPGUID deviceGUID = NULL;
RPC_CSTR wszUuid = NULL;
HRESULT hr = E_FAIL;
+ std::string strDeviceGUID = device;
std::list<DSDevice> DSDeviceList;
std::string deviceFriendlyName;
DirectSoundEnumerate(DSEnumCallback, &DSDeviceList);
+ if(StringUtils::EndsWith(device, std::string("default")))
+ strDeviceGUID = GetDefaultDevice();
+
for (std::list<DSDevice>::iterator itt = DSDeviceList.begin(); itt != DSDeviceList.end(); ++itt)
{
if ((*itt).lpGuid)
hr = (UuidToString((*itt).lpGuid, &wszUuid));
std::string sztmp = (char*)wszUuid;
std::string szGUID = "{" + std::string(sztmp.begin(), sztmp.end()) + "}";
- if (strcasecmp(szGUID.c_str(), device.c_str()) == 0)
+ if (strcasecmp(szGUID.c_str(), strDeviceGUID.c_str()) == 0)
{
deviceGUID = (*itt).lpGuid;
deviceFriendlyName = (*itt).name.c_str();
break;
}
}
- if (hr == RPC_S_OK) RpcStringFree(&wszUuid);
+ if (hr == RPC_S_OK) RpcStringFree(&wszUuid);
}
hr = DirectSoundCreate(deviceGUID, &m_pDSound, NULL);
if (FAILED(hr))
{
- CLog::Log(LOGERROR, __FUNCTION__": Failed to create the DirectSound device.");
- CLog::Log(LOGERROR, __FUNCTION__": DSErr: %s", dserr2str(hr));
- return false;
+ CLog::Log(LOGERROR, __FUNCTION__": Failed to create the DirectSound device %s with error %s, trying the default device.", deviceFriendlyName.c_str(), dserr2str(hr));
+ hr = DirectSoundCreate(NULL, &m_pDSound, NULL);
+ if (FAILED(hr))
+ {
+ CLog::Log(LOGERROR, __FUNCTION__": Failed to create the default DirectSound device with error %s.", dserr2str(hr));
+ return false;
+ }
}
HWND tmp_hWnd;
return false;
}
-unsigned int CAESinkDirectSound::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio)
+unsigned int CAESinkDirectSound::AddPackets(uint8_t *data, unsigned int frames, bool hasAudio, bool blocking)
{
if (!m_initialized)
return 0;
while (GetSpace() < total)
{
- if (m_isDirtyDS)
+ if(m_isDirtyDS)
return INT_MAX;
else
- return 0;
+ {
+ if(blocking)
+ Sleep(total * 1000 / m_AvgBytesPerSec);
+ else
+ return 0;
+ }
}
while (len)
DWORD size = 0, sizeWrap = 0;
if (m_BufferOffset >= m_dwBufferLen) // Wrap-around manually
m_BufferOffset = 0;
- HRESULT res = m_pBuffer->Lock(m_BufferOffset, m_dwChunkSize, &start, &size, &startWrap, &sizeWrap, 0);
+ DWORD dwWriteBytes = std::min((int)m_dwChunkSize, (int)len);
+ HRESULT res = m_pBuffer->Lock(m_BufferOffset, dwWriteBytes, &start, &size, &startWrap, &sizeWrap, 0);
if (DS_OK != res)
{
CLog::Log(LOGERROR, __FUNCTION__ ": Unable to lock buffer at offset %u. HRESULT: 0x%08x", m_BufferOffset, res);
m_pBuffer->Stop();
}
+void CAESinkDirectSound::Drain()
+{
+ if (!m_initialized || m_isDirtyDS)
+ return;
+
+ m_pBuffer->Stop();
+ HRESULT res = m_pBuffer->SetCurrentPosition(0);
+ if (DS_OK != res)
+ {
+ CLog::Log(LOGERROR,__FUNCTION__ ": SetCurrentPosition failed. Unable to determine buffer status. HRESULT = 0x%08x", res);
+ m_isDirtyDS = true;
+ return;
+ }
+ m_BufferOffset = 0;
+ UpdateCacheStatus();
+}
+
double CAESinkDirectSound::GetDelay()
{
if (!m_initialized)
HRESULT hr;
+ std::string strDD = GetDefaultDevice();
+
/* See if we are on Windows XP */
if (!g_sysinfo.IsWindowsVersionAtLeast(CSysInfo::WindowsVersionVista))
{
deviceInfo.m_sampleRates.push_back((DWORD) 96000);
deviceInfoList.push_back(deviceInfo);
+
+ // add the default device with m_deviceName = default
+ if(strDD == deviceInfo.m_deviceName)
+ {
+ deviceInfo.m_deviceName = std::string("default");
+ deviceInfo.m_displayName = std::string("default");
+ deviceInfo.m_displayNameExtra = std::string("");
+ deviceInfoList.push_back(deviceInfo);
+ }
}
RpcStringFree(&cszGUID);
deviceInfo.m_deviceType = aeDeviceType;
deviceInfoList.push_back(deviceInfo);
- }
- // since AE takes the first device in deviceInfoList as default audio device we need
- // to sort it in order to use the real default device
- if(deviceInfoList.size() > 1)
- {
- std::string strDD = GetDefaultDevice();
- for (AEDeviceInfoList::iterator itt = deviceInfoList.begin(); itt != deviceInfoList.end(); ++itt)
+ // add the default device with m_deviceName = default
+ if(strDD == strDevName)
{
- CAEDeviceInfo devInfo = *itt;
- if(devInfo.m_deviceName == strDD)
- {
- deviceInfoList.erase(itt);
- deviceInfoList.insert(deviceInfoList.begin(), devInfo);
- break;
- }
+ deviceInfo.m_deviceName = std::string("default");
+ deviceInfo.m_displayName = std::string("default");
+ deviceInfo.m_displayNameExtra = std::string("");
+ deviceInfoList.push_back(deviceInfo);
}
}
bool CAESinkDirectSound::UpdateCacheStatus()
{
CSingleLock lock (m_runLock);
- // TODO: Check to see if we may have cycled around since last time
- unsigned int time = XbmcThreads::SystemClockMillis();
- if (time == m_LastCacheCheck)
- return true; // Don't recalc more frequently than once/ms (that is our max resolution anyway)
DWORD playCursor = 0, writeCursor = 0;
HRESULT res = m_pBuffer->GetCurrentPosition(&playCursor, &writeCursor); // Get the current playback and safe write positions
return false;
}
- m_LastCacheCheck = time;
// Check the state of the ring buffer (P->O->W == underrun)
// These are the logical situations that can occur
// O: CurrentOffset W: WriteCursor P: PlayCursor
return false;
}
}
- else m_BufferTimeouts = 0;
+ else
+ m_BufferTimeouts = 0;
// Calculate available space in the ring buffer
if (playCursor == m_BufferOffset && m_BufferOffset == writeCursor) // Playback is stopped and we are all at the same place
{
/* Return false to force re-init by engine */
return false;
-}
\ No newline at end of file
+}