From: <man...@us...> - 2015-05-05 10:01:55
|
Revision: 5046 http://sourceforge.net/p/modplug/code/5046 Author: manxorist Date: 2015-05-05 10:01:42 +0000 (Tue, 05 May 2015) Log Message: ----------- [Ref] sounddev: Kill SoundDevice::ID and replace all occurences with the unique and stable SoundDevice::Identifier or a per-session unique SoundDevice::Manager::GlobalID. [Ref] sounddev: For WaveOut devices, store the WaveOut device index as string in internalID. [Ref] sounddev: Convert the PortAudio internalID from per-HostAPI index to the global PortAudio PA_DeviceIndex. This simplifies a whole lot of per-HostAPI device counting and confusing number conversions. [Mod] sounddev: Sort sound devices depending on OS version. [Mod] sounddev: Show PortAudio WDM-KS devices as WaveRT in Vista and newer. Modified Paths: -------------- trunk/OpenMPT/mptrack/Mpdlgs.cpp trunk/OpenMPT/mptrack/Mptrack.cpp trunk/OpenMPT/mptrack/TrackerSettings.cpp trunk/OpenMPT/mptrack/TrackerSettings.h trunk/OpenMPT/sounddev/SoundDevice.cpp trunk/OpenMPT/sounddev/SoundDevice.h trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp trunk/OpenMPT/sounddev/SoundDeviceManager.cpp trunk/OpenMPT/sounddev/SoundDeviceManager.h trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp trunk/OpenMPT/sounddev/SoundDevicePortAudio.h trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp trunk/OpenMPT/sounddev/SoundDeviceWaveout.h Modified: trunk/OpenMPT/mptrack/Mpdlgs.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mpdlgs.cpp 2015-05-04 22:41:44 UTC (rev 5045) +++ trunk/OpenMPT/mptrack/Mpdlgs.cpp 2015-05-05 10:01:42 UTC (rev 5046) @@ -344,7 +344,6 @@ m_CbnDevice.ResetContent(); m_CbnDevice.SetImageList(&CMainFrame::GetMainFrame()->m_MiscIcons); - COMBOBOXEXITEM cbi; UINT iItem = 0; for(std::vector<SoundDevice::Info>::const_iterator it = theApp.GetSoundDevicesManager()->begin(); it != theApp.GetSoundDevicesManager()->end(); ++it) @@ -352,7 +351,7 @@ if(!TrackerSettings::Instance().m_MorePortaudio) { - if(it->id.GetType() == SoundDevice::TypePORTAUDIO_ASIO || it->id.GetType() == SoundDevice::TypePORTAUDIO_DS || it->id.GetType() == SoundDevice::TypePORTAUDIO_WMME) + if(it->type == SoundDevice::TypePORTAUDIO_DS || it->type == SoundDevice::TypePORTAUDIO_WMME) { // skip those portaudio apis that are already implemented via our own SoundDevice class // can be overwritten via [Sound Settings]MorePortaudio=1 @@ -361,53 +360,60 @@ } { + COMBOBOXEXITEM cbi; + MemsetZero(cbi); CString name = mpt::ToCString(it->name); - cbi.mask = CBEIF_IMAGE | CBEIF_LPARAM | CBEIF_TEXT | CBEIF_SELECTEDIMAGE | CBEIF_OVERLAY; + cbi.mask = CBEIF_LPARAM | CBEIF_TEXT | CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_OVERLAY; cbi.iItem = iItem; cbi.cchTextMax = 0; - switch(it->id.GetType()) + if(it->type == SoundDevice::TypeWAVEOUT) { - case SoundDevice::TypeWAVEOUT: - case SoundDevice::TypePORTAUDIO_WMME: cbi.iImage = IMAGE_WAVEOUT; - break; - case SoundDevice::TypeDSOUND: - case SoundDevice::TypePORTAUDIO_DS: + } else if(it->type == SoundDevice::TypePORTAUDIO_WMME) + { + cbi.iImage = IMAGE_WAVEOUT; + } else if(it->type == SoundDevice::TypeDSOUND) + { cbi.iImage = IMAGE_DIRECTX; - break; - case SoundDevice::TypeASIO: - case SoundDevice::TypePORTAUDIO_ASIO: + } else if(it->type == SoundDevice::TypePORTAUDIO_DS) + { + cbi.iImage = IMAGE_DIRECTX; + } else if(it->type == SoundDevice::TypeASIO) + { cbi.iImage = IMAGE_ASIO; - break; - case SoundDevice::TypePORTAUDIO_WASAPI: + } else if(it->type == SoundDevice::TypePORTAUDIO_WASAPI) + { // No real image available for now, // prepend API name to name and misuse another icon cbi.iImage = IMAGE_SAMPLEMUTE; - name = mpt::ToCString(it->apiName) + TEXT(" - ") + name; - break; - case SoundDevice::TypePORTAUDIO_WDMKS: + name = mpt::ToCString(it->apiName) + _T(" - ") + name; + } else if(it->type == SoundDevice::TypePORTAUDIO_WDMKS) + { // No real image available for now, // prepend API name to name and misuse another icon. cbi.iImage = IMAGE_CHIP; - name = mpt::ToCString(it->apiName) + TEXT(" - ") + name; - break; - default: - cbi.iImage = IMAGE_WAVEOUT; - break; + name = mpt::ToCString(it->apiName) + _T(" - ") + name; + } else + { + cbi.mask &= ~(CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_OVERLAY); + std::vector<mpt::ustring> api = it->apiPath; + api.push_back(it->apiName); + name = mpt::ToCString(mpt::String::Combine(api, MPT_USTRING(" - "))) + _T(" - ") + name; } if(it->isDefault) { - name += " (Default)"; + name += _T(" (Default)"); } cbi.iSelectedImage = cbi.iImage; cbi.iOverlay = cbi.iImage; cbi.iIndent = 0; - cbi.lParam = it->id.GetIdRaw(); - TCHAR tmp[256]; - _tcscpy(tmp, name); + cbi.lParam = theApp.GetSoundDevicesManager()->GetGlobalID(it->GetIdentifier()); + TCHAR tmp[1024]; + MemsetZero(tmp); + lstrcpyn(tmp, name, 1023); cbi.pszText = tmp; int pos = m_CbnDevice.InsertItem(&cbi); - if(cbi.lParam == m_CurrentDeviceInfo.id.GetIdRaw()) + if(static_cast<SoundDevice::Manager::GlobalID>(cbi.lParam) == theApp.GetSoundDevicesManager()->GetGlobalID(m_CurrentDeviceInfo.GetIdentifier())) { m_CbnDevice.SetCurSel(pos); } @@ -619,7 +625,7 @@ int n = m_CbnDevice.GetCurSel(); if(n >= 0) { - SetDevice(theApp.GetSoundDevicesManager()->FindDeviceInfo(SoundDevice::ID::FromIdRaw(m_CbnDevice.GetItemData(n))).GetIdentifier()); + SetDevice(theApp.GetSoundDevicesManager()->FindDeviceInfo(static_cast<SoundDevice::Manager::GlobalID>(m_CbnDevice.GetItemData(n))).GetIdentifier()); UpdateDevice(); OnSettingsChanged(); } @@ -646,7 +652,7 @@ //---------------------------------------------- { theApp.GetSoundDevicesManager()->OpenDriverSettings( - theApp.GetSoundDevicesManager()->FindDeviceInfo(SoundDevice::ID::FromIdRaw(m_CbnDevice.GetItemData(m_CbnDevice.GetCurSel()))).GetIdentifier(), + theApp.GetSoundDevicesManager()->FindDeviceInfo(static_cast<SoundDevice::Manager::GlobalID>(m_CbnDevice.GetItemData(m_CbnDevice.GetCurSel()))).GetIdentifier(), CMainFrame::GetMainFrame(), CMainFrame::GetMainFrame()->gpSoundDevice ); Modified: trunk/OpenMPT/mptrack/Mptrack.cpp =================================================================== --- trunk/OpenMPT/mptrack/Mptrack.cpp 2015-05-04 22:41:44 UTC (rev 5045) +++ trunk/OpenMPT/mptrack/Mptrack.cpp 2015-05-05 10:01:42 UTC (rev 5046) @@ -1003,7 +1003,7 @@ if(TrackerSettings::Instance().m_SoundDeviceSettingsUseOldDefaults) { // get the old default device - TrackerSettings::Instance().SetSoundDeviceIdentifier(m_pSoundDevicesManager->FindDeviceInfo(TrackerSettings::Instance().m_SoundDeviceID_DEPRECATED).GetIdentifier()); + TrackerSettings::Instance().SetSoundDeviceIdentifier(SoundDevice::Legacy::FindDeviceInfo(*m_pSoundDevicesManager, TrackerSettings::Instance().m_SoundDeviceID_DEPRECATED).GetIdentifier()); // apply old global sound device settings to each found device for(std::vector<SoundDevice::Info>::const_iterator it = m_pSoundDevicesManager->begin(); it != m_pSoundDevicesManager->end(); ++it) { Modified: trunk/OpenMPT/mptrack/TrackerSettings.cpp =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.cpp 2015-05-04 22:41:44 UTC (rev 5045) +++ trunk/OpenMPT/mptrack/TrackerSettings.cpp 2015-05-05 10:01:42 UTC (rev 5046) @@ -177,7 +177,7 @@ , m_SoundSettingsOpenDeviceAtStartup(conf, "Sound Settings", "OpenDeviceAtStartup", false) , m_SoundSettingsStopMode(conf, "Sound Settings", "StopMode", SoundDeviceStopModeClosed) , m_SoundDeviceSettingsUseOldDefaults(false) - , m_SoundDeviceID_DEPRECATED(SoundDevice::ID()) + , m_SoundDeviceID_DEPRECATED(SoundDevice::Legacy::ID()) , m_SoundDeviceDirectSoundOldDefaultIdentifier(false) , m_SoundDeviceIdentifier(conf, "Sound Settings", "Device", SoundDevice::Identifier()) , m_SoundDevicePreferSameTypeIfDeviceUnavailable(conf, "Sound Settings", "PreferSameTypeIfDeviceUnavailable", false) @@ -426,7 +426,7 @@ } if(storedVersion < MAKE_VERSION_NUMERIC(1,22,07,04)) { - m_SoundDeviceID_DEPRECATED = conf.Read<SoundDevice::ID>("Sound Settings", "WaveDevice", SoundDevice::ID()); + m_SoundDeviceID_DEPRECATED = conf.Read<SoundDevice::Legacy::ID>("Sound Settings", "WaveDevice", SoundDevice::Legacy::ID()); Setting<uint32> m_BufferLength_DEPRECATED(conf, "Sound Settings", "BufferLength", 50); Setting<uint32> m_LatencyMS(conf, "Sound Settings", "Latency", Util::Round<int32>(SoundDevice::Settings().Latency * 1000.0)); Setting<uint32> m_UpdateIntervalMS(conf, "Sound Settings", "UpdateInterval", Util::Round<int32>(SoundDevice::Settings().UpdateInterval * 1000.0)); @@ -441,7 +441,7 @@ { if(m_BufferLength_DEPRECATED < 1) m_BufferLength_DEPRECATED = 1; // 1ms if(m_BufferLength_DEPRECATED > 1000) m_BufferLength_DEPRECATED = 1000; // 1sec - if(m_SoundDeviceID_DEPRECATED.GetType() == SoundDevice::TypeASIO) + if((m_SoundDeviceID_DEPRECATED & SoundDevice::Legacy::MaskType) == SoundDevice::Legacy::TypeASIO) { m_LatencyMS = m_BufferLength_DEPRECATED; m_UpdateIntervalMS = m_BufferLength_DEPRECATED / 8; @@ -649,7 +649,7 @@ ChannelMapping = SoundDevice::ChannelMapping(Channels); } // store informational data (not read back, just to allow the user to mock with the raw ini file) - conf.Write(L"Sound Settings", mpt::ToWide(deviceInfo.GetIdentifier()) + L"_" + L"ID", deviceInfo.id); + conf.Write(L"Sound Settings", mpt::ToWide(deviceInfo.GetIdentifier()) + L"_" + L"Type", deviceInfo.type); conf.Write(L"Sound Settings", mpt::ToWide(deviceInfo.GetIdentifier()) + L"_" + L"InternalID", deviceInfo.internalID); conf.Write(L"Sound Settings", mpt::ToWide(deviceInfo.GetIdentifier()) + L"_" + L"API", deviceInfo.apiName); conf.Write(L"Sound Settings", mpt::ToWide(deviceInfo.GetIdentifier()) + L"_" + L"Name", deviceInfo.name); Modified: trunk/OpenMPT/mptrack/TrackerSettings.h =================================================================== --- trunk/OpenMPT/mptrack/TrackerSettings.h 2015-05-04 22:41:44 UTC (rev 5045) +++ trunk/OpenMPT/mptrack/TrackerSettings.h 2015-05-05 10:01:42 UTC (rev 5046) @@ -261,9 +261,6 @@ template<> inline SettingValue ToSettingValue(const std::vector<uint32> &val) { return mpt::String::Combine(val); } template<> inline std::vector<uint32> FromSettingValue(const SettingValue &val) { return mpt::String::Split<uint32>(val); } -template<> inline SettingValue ToSettingValue(const SoundDevice::ID &val) { return SettingValue(int32(val.GetIdRaw())); } -template<> inline SoundDevice::ID FromSettingValue(const SettingValue &val) { return SoundDevice::ID::FromIdRaw(val.as<int32>()); } - template<> inline SettingValue ToSettingValue(const SampleFormat &val) { return SettingValue(int32(val.value)); } template<> inline SampleFormat FromSettingValue(const SettingValue &val) { return SampleFormatEnum(val.as<int32>()); } @@ -442,7 +439,7 @@ Setting<SoundDeviceStopMode> m_SoundSettingsStopMode; bool m_SoundDeviceSettingsUseOldDefaults; - SoundDevice::ID m_SoundDeviceID_DEPRECATED; + SoundDevice::Legacy::ID m_SoundDeviceID_DEPRECATED; SoundDevice::Settings m_SoundDeviceSettingsDefaults; SoundDevice::Settings GetSoundDeviceSettingsDefaults() const; bool m_SoundDeviceDirectSoundOldDefaultIdentifier; Modified: trunk/OpenMPT/sounddev/SoundDevice.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.cpp 2015-05-04 22:41:44 UTC (rev 5045) +++ trunk/OpenMPT/sounddev/SoundDevice.cpp 2015-05-05 10:01:42 UTC (rev 5046) @@ -16,6 +16,7 @@ #include "../common/misc_util.h" #include "../common/StringFixer.h" +#include <map> OPENMPT_NAMESPACE_BEGIN @@ -24,24 +25,6 @@ namespace SoundDevice { -mpt::ustring TypeToString(SoundDevice::Type type, bool verbose) -//------------------------------------------------------------- -{ - switch(type) - { - case TypeWAVEOUT: return MPT_USTRING("WaveOut"); break; - case TypeDSOUND: return MPT_USTRING("DirectSound"); break; - case TypeASIO: return MPT_USTRING("ASIO"); break; - case TypePORTAUDIO_WASAPI: return (verbose ? MPT_USTRING("PortAudio") : MPT_USTRING("")) + MPT_USTRING("WASAPI"); break; - case TypePORTAUDIO_WDMKS: return (verbose ? MPT_USTRING("PortAudio") : MPT_USTRING("")) + MPT_USTRING("WDM-KS"); break; - case TypePORTAUDIO_WMME: return (verbose ? MPT_USTRING("PortAudio") : MPT_USTRING("")) + MPT_USTRING("MME"); break; - case TypePORTAUDIO_DS: return (verbose ? MPT_USTRING("PortAudio") : MPT_USTRING("")) + MPT_USTRING("DS"); break; - case TypePORTAUDIO_ASIO: return (verbose ? MPT_USTRING("PortAudio") : MPT_USTRING("")) + MPT_USTRING("ASIO"); break; - } - return mpt::ustring(); -} - - ChannelMapping::ChannelMapping() //------------------------------ { Modified: trunk/OpenMPT/sounddev/SoundDevice.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevice.h 2015-05-04 22:41:44 UTC (rev 5045) +++ trunk/OpenMPT/sounddev/SoundDevice.h 2015-05-05 10:01:42 UTC (rev 5046) @@ -17,8 +17,6 @@ #include "../common/mptAtomic.h" #include "../soundlib/SampleFormat.h" -#include <bitset> -#include <map> #include <vector> @@ -110,107 +108,35 @@ // SoundDevice::Base Interface // -enum Type -{ - // do not change old values, these get saved to the ini - TypeINVALID =-1, - TypeWAVEOUT = 0, - TypeDSOUND = 1, - TypeASIO = 2, - TypePORTAUDIO_WASAPI = 3, - TypePORTAUDIO_WDMKS = 4, - TypePORTAUDIO_WMME = 5, - TypePORTAUDIO_DS = 6, - TypePORTAUDIO_ASIO = 7, - TypeNUM_DEVTYPES -}; -typedef std::bitset<TypeNUM_DEVTYPES> TypesSet; +static const MPT_UCHAR_TYPE TypeWAVEOUT [] = MPT_ULITERAL("WaveOut"); +static const MPT_UCHAR_TYPE TypeDSOUND [] = MPT_ULITERAL("DirectSound"); +static const MPT_UCHAR_TYPE TypeASIO [] = MPT_ULITERAL("ASIO"); +static const MPT_UCHAR_TYPE TypePORTAUDIO_WASAPI [] = MPT_ULITERAL("WASAPI"); +static const MPT_UCHAR_TYPE TypePORTAUDIO_WDMKS [] = MPT_ULITERAL("WDM-KS"); +static const MPT_UCHAR_TYPE TypePORTAUDIO_WMME [] = MPT_ULITERAL("MME"); +static const MPT_UCHAR_TYPE TypePORTAUDIO_DS [] = MPT_ULITERAL("DS"); -mpt::ustring TypeToString(SoundDevice::Type type, bool verbose = false); +typedef mpt::ustring Type; -typedef uint8 Index; -template<typename T> -bool IndexIsValid(const T & x) -{ - return 0 <= x && x <= std::numeric_limits<Index>::max(); -} - -//====== -class ID -//====== -{ -private: - SoundDevice::Type type; - SoundDevice::Index index; -public: - ID() : type(TypeWAVEOUT), index(0) {} - ID(SoundDevice::Type type, SoundDevice::Index index) - : type(type) - , index(index) - { - return; - } - bool IsValid() const - { - return (type > TypeINVALID); - } - SoundDevice::Type GetType() const { return type; } - SoundDevice::Index GetIndex() const { return index; } - bool operator == (const SoundDevice::ID &cmp) const - { - return (type == cmp.type) && (index == cmp.index); - } - - bool operator != (const SoundDevice::ID &cmp) const - { - return (type != cmp.type) || (index != cmp.index); - } - bool operator < (const SoundDevice::ID &cmp) const - { - return (type < cmp.type) || (type == cmp.type && index < cmp.index); - } -public: - // Do not change these. These functions are used to manipulate the value that gets stored in the settings. - template<typename T> - static SoundDevice::ID FromIdRaw(T id_) - { - uint16 id = static_cast<uint16>(id_); - return SoundDevice::ID((SoundDevice::Type)((id>>8)&0xff), (id>>0)&0xff); - } - uint16 GetIdRaw() const - { - return static_cast<uint16>(((int)type<<8) | (index<<0)); - } -}; - - typedef mpt::ustring Identifier; SoundDevice::Type ParseType(const SoundDevice::Identifier &identifier); - struct Info { - SoundDevice::ID id; - mpt::ustring name; - mpt::ustring apiName; + SoundDevice::Type type; mpt::ustring internalID; + mpt::ustring name; // user visible + mpt::ustring apiName; // user visible + std::vector<mpt::ustring> apiPath; // i.e. Wine-support, PortAudio bool isDefault; - Info() : id(TypeINVALID, 0), isDefault(false) { } - Info(SoundDevice::ID id, const mpt::ustring &name, const mpt::ustring &apiName, const mpt::ustring &internalID = mpt::ustring()) - : id(id) - , name(name) - , apiName(apiName) - , internalID(internalID) - , isDefault(false) - { - return; - } + bool useNameAsIdentifier; + Info() : isDefault(false), useNameAsIdentifier(false) { } bool IsValid() const { - return id.IsValid(); + return !type.empty() && !internalID.empty(); } SoundDevice::Identifier GetIdentifier() const { @@ -218,13 +144,11 @@ { return mpt::ustring(); } - mpt::ustring result = apiName; + mpt::ustring result = mpt::ustring(); + result += type; result += MPT_USTRING("_"); - if(!internalID.empty()) + if(useNameAsIdentifier) { - result += internalID; // safe to not contain special characters - } else if(!name.empty()) - { // UTF8-encode the name and convert the utf8 to hex. // This ensures that no special characters are contained in the configuration key. std::string utf8String = mpt::ToCharset(mpt::CharsetUTF8, name); @@ -232,7 +156,7 @@ result += hexString; } else { - result += mpt::ufmt::dec(id.GetIndex()); + result += internalID; // safe to not contain special characters } return result; } @@ -604,9 +528,7 @@ protected: - SoundDevice::ID GetDeviceID() const { return m_Info.id; } - SoundDevice::Type GetDeviceType() const { return m_Info.id.GetType(); } - SoundDevice::Index GetDeviceIndex() const { return m_Info.id.GetIndex(); } + SoundDevice::Type GetDeviceType() const { return m_Info.type; } mpt::ustring GetDeviceInternalID() const { return m_Info.internalID; } SoundDevice::Identifier GetDeviceIdentifier() const { return m_Info.GetIdentifier(); } @@ -700,6 +622,16 @@ namespace Legacy { +typedef uint16 ID; +static const SoundDevice::Legacy::ID MaskType = 0xff00; +static const SoundDevice::Legacy::ID MaskIndex = 0x00ff; +static const SoundDevice::Legacy::ID TypeWAVEOUT = 0; +static const SoundDevice::Legacy::ID TypeDSOUND = 1; +static const SoundDevice::Legacy::ID TypeASIO = 2; +static const SoundDevice::Legacy::ID TypePORTAUDIO_WASAPI = 3; +static const SoundDevice::Legacy::ID TypePORTAUDIO_WDMKS = 4; +static const SoundDevice::Legacy::ID TypePORTAUDIO_WMME = 5; +static const SoundDevice::Legacy::ID TypePORTAUDIO_DS = 6; mpt::ustring GetDirectSoundDefaultDeviceIdentifierPre_1_25_00_04(); mpt::ustring GetDirectSoundDefaultDeviceIdentifier_1_25_00_04(); } Modified: trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2015-05-04 22:41:44 UTC (rev 5045) +++ trunk/OpenMPT/sounddev/SoundDeviceASIO.cpp 2015-05-05 10:01:42 UTC (rev 5046) @@ -158,11 +158,14 @@ if(Util::IsCLSID(mpt::ToWide(internalID))) { Log(mpt::String::Print("ASIO: clsid=%1", mpt::ToLocale(internalID))); - if(SoundDevice::IndexIsValid(devices.size())) - { - // everything ok - devices.push_back(SoundDevice::Info(SoundDevice::ID(TypeASIO, static_cast<SoundDevice::Index>(devices.size())), description, SoundDevice::TypeToString(TypeASIO), internalID)); - } + SoundDevice::Info info; + info.type = TypeASIO; + info.internalID = internalID; + info.apiName = MPT_USTRING("ASIO"); + info.name = description; + info.useNameAsIdentifier = false; + info.isDefault = false; + devices.push_back(info); } } @@ -255,8 +258,7 @@ InitMembers(); - Log(mpt::String::Print("ASIO: Open(%1:'%2'): %3-bit, %4 channels, %5Hz, hw-timing=%6" - , GetDeviceIndex() + Log(mpt::String::Print("ASIO: Open('%1'): %2-bit, %3 channels, %4Hz, hw-timing=%5" , mpt::ToLocale(GetDeviceInternalID()) , m_Settings.sampleFormat.GetBitsPerSample() , m_Settings.Channels Modified: trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp 2015-05-04 22:41:44 UTC (rev 5045) +++ trunk/OpenMPT/sounddev/SoundDeviceDirectSound.cpp 2015-05-05 10:01:42 UTC (rev 5046) @@ -85,21 +85,20 @@ { return TRUE; } - if(!SoundDevice::IndexIsValid(devices.size())) - { - return FALSE; - } SoundDevice::Info info; - info.id = SoundDevice::ID(TypeDSOUND, static_cast<SoundDevice::Index>(devices.size())); - info.name = mpt::ToUnicode(lpstrDescription); - info.apiName = SoundDevice::TypeToString(TypeDSOUND); - if(lpGuid) + info.type = TypeDSOUND; + if(!lpGuid) { - info.internalID = mpt::ToUnicode(Util::GUIDToString(*lpGuid)); + info.isDefault = true; + info.internalID = mpt::ToUnicode(Util::GUIDToString(GUID())); } else { - info.internalID = mpt::ToUnicode(Util::GUIDToString(GUID())); + info.isDefault = false; + info.internalID = mpt::ToUnicode(Util::GUIDToString(*lpGuid)); } + info.name = mpt::ToUnicode(lpstrDescription); + info.apiName = MPT_USTRING("DirectSound"); + info.useNameAsIdentifier = false; devices.push_back(info); return TRUE; } Modified: trunk/OpenMPT/sounddev/SoundDeviceManager.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceManager.cpp 2015-05-04 22:41:44 UTC (rev 5045) +++ trunk/OpenMPT/sounddev/SoundDeviceManager.cpp 2015-05-05 10:01:42 UTC (rev 5046) @@ -32,6 +32,20 @@ // + struct CompareType + { + std::map<SoundDevice::Type, int> ordering; + CompareType(const std::map<SoundDevice::Type, int> &ordering) + : ordering(ordering) + { + return; + } + bool operator () (const SoundDevice::Info &x, const SoundDevice::Info &y) + { + return (ordering[x.type] > ordering[y.type]); + } + }; + void Manager::ReEnumerate() //------------------------- { @@ -52,6 +66,14 @@ const std::vector<SoundDevice::Info> infos = CWaveDevice::EnumerateDevices(); m_SoundDevices.insert(m_SoundDevices.end(), infos.begin(), infos.end()); } + // kind of deprecated by now +#ifndef NO_DSOUND + if(IsComponentAvailable(m_DirectSound)) + { + const std::vector<SoundDevice::Info> infos = CDSoundDevice::EnumerateDevices(); + m_SoundDevices.insert(m_SoundDevices.end(), infos.begin(), infos.end()); + } +#endif // NO_DSOUND #ifndef NO_ASIO if(IsComponentAvailable(m_ASIO)) @@ -64,49 +86,56 @@ #ifndef NO_PORTAUDIO if(IsComponentAvailable(m_PortAudio)) { - const std::vector<SoundDevice::Info> infos = CPortaudioDevice::EnumerateDevices(TypePORTAUDIO_WASAPI); + const std::vector<SoundDevice::Info> infos = CPortaudioDevice::EnumerateDevices(); m_SoundDevices.insert(m_SoundDevices.end(), infos.begin(), infos.end()); } - if(IsComponentAvailable(m_PortAudio)) - { - const std::vector<SoundDevice::Info> infos = CPortaudioDevice::EnumerateDevices(TypePORTAUDIO_WDMKS); - m_SoundDevices.insert(m_SoundDevices.end(), infos.begin(), infos.end()); - } #endif // NO_PORTAUDIO - // kind of deprecated by now -#ifndef NO_DSOUND - if(IsComponentAvailable(m_DirectSound)) - { - const std::vector<SoundDevice::Info> infos = CDSoundDevice::EnumerateDevices(); - m_SoundDevices.insert(m_SoundDevices.end(), infos.begin(), infos.end()); + std::map<SoundDevice::Type, int> typePriorities; + if(mpt::Windows::Version::IsWine()) + { // Wine + typePriorities[SoundDevice::TypeDSOUND] = 29; + typePriorities[SoundDevice::TypeWAVEOUT] = 28; + typePriorities[SoundDevice::TypePORTAUDIO_WASAPI] = 21; + typePriorities[SoundDevice::TypePORTAUDIO_WMME] = 19; + typePriorities[SoundDevice::TypePORTAUDIO_DS] = 18; + typePriorities[SoundDevice::TypeASIO] = 10; + typePriorities[SoundDevice::TypePORTAUDIO_WDMKS] = -1; + } else if(!mpt::Windows::Version::IsNT()) + { // Win9x + typePriorities[SoundDevice::TypeWAVEOUT] = 29; + typePriorities[SoundDevice::TypeDSOUND] = 28; + typePriorities[SoundDevice::TypePORTAUDIO_WMME] = 19; + typePriorities[SoundDevice::TypePORTAUDIO_DS] = 18; + typePriorities[SoundDevice::TypeASIO] = 1; + typePriorities[SoundDevice::TypePORTAUDIO_WDMKS] = -1; + typePriorities[SoundDevice::TypePORTAUDIO_WASAPI] = -2; + } else if(!mpt::Windows::Version::IsAtLeast(mpt::Windows::Version::WinVista)) + { // WinXP + typePriorities[SoundDevice::TypeWAVEOUT] = 29; + typePriorities[SoundDevice::TypeASIO] = 28; + typePriorities[SoundDevice::TypeDSOUND] = 27; + typePriorities[SoundDevice::TypePORTAUDIO_WDMKS] = 26; + typePriorities[SoundDevice::TypePORTAUDIO_WMME] = 19; + typePriorities[SoundDevice::TypePORTAUDIO_DS] = 17; + typePriorities[SoundDevice::TypePORTAUDIO_WASAPI] = -1; + } else + { // >=Vista + typePriorities[SoundDevice::TypeWAVEOUT] = 29; + typePriorities[SoundDevice::TypePORTAUDIO_WASAPI] = 28; + typePriorities[SoundDevice::TypeASIO] = 27; + typePriorities[SoundDevice::TypePORTAUDIO_WDMKS] = 26; + typePriorities[SoundDevice::TypePORTAUDIO_WMME] = 19; + typePriorities[SoundDevice::TypeDSOUND] = -1; + typePriorities[SoundDevice::TypePORTAUDIO_DS] = -2; } -#endif // NO_DSOUND + std::stable_sort(m_SoundDevices.begin(), m_SoundDevices.end(), CompareType(typePriorities)); - // duplicate devices, only used if [Sound Settings]MorePortaudio=1 -#ifndef NO_PORTAUDIO - if(IsComponentAvailable(m_PortAudio)) - { - const std::vector<SoundDevice::Info> infos = CPortaudioDevice::EnumerateDevices(TypePORTAUDIO_WMME); - m_SoundDevices.insert(m_SoundDevices.end(), infos.begin(), infos.end()); - } - if(IsComponentAvailable(m_PortAudio)) - { - const std::vector<SoundDevice::Info> infos = CPortaudioDevice::EnumerateDevices(TypePORTAUDIO_ASIO); - m_SoundDevices.insert(m_SoundDevices.end(), infos.begin(), infos.end()); - } - if(IsComponentAvailable(m_PortAudio)) - { - const std::vector<SoundDevice::Info> infos = CPortaudioDevice::EnumerateDevices(TypePORTAUDIO_DS); - m_SoundDevices.insert(m_SoundDevices.end(), infos.begin(), infos.end()); - } -#endif // NO_PORTAUDIO - Log(LogDebug, MPT_USTRING("Sound Devices enumerated:")); for(std::size_t i = 0; i < m_SoundDevices.size(); ++i) { Log(LogDebug, mpt::String::Print(MPT_USTRING(" Identifier : %1") , m_SoundDevices[i].GetIdentifier())); - Log(LogDebug, mpt::String::Print(MPT_USTRING(" ID : %1.%2"), static_cast<uint32>(m_SoundDevices[i].id.GetType()), m_SoundDevices[i].id.GetIndex())); + Log(LogDebug, mpt::String::Print(MPT_USTRING(" Type : %1") , m_SoundDevices[i].type)); Log(LogDebug, mpt::String::Print(MPT_USTRING(" InternalID: %1") , m_SoundDevices[i].internalID)); Log(LogDebug, mpt::String::Print(MPT_USTRING(" API Name : %1") , m_SoundDevices[i].apiName)); Log(LogDebug, mpt::String::Print(MPT_USTRING(" Name : %1") , m_SoundDevices[i].name)); @@ -115,20 +144,31 @@ } -SoundDevice::Info Manager::FindDeviceInfo(SoundDevice::ID id) const -//----------------------------------------------------------------- +SoundDevice::Manager::GlobalID Manager::GetGlobalID(SoundDevice::Identifier identifier) const +//------------------------------------------------------------------------------------------- { - for(std::vector<SoundDevice::Info>::const_iterator it = begin(); it != end(); ++it) + for(std::size_t i = 0; i < m_SoundDevices.size(); ++i) { - if(it->id == id) + if(m_SoundDevices[i].GetIdentifier() == identifier) { - return *it; + return i; } } - return SoundDevice::Info(); + return ~SoundDevice::Manager::GlobalID(); } +SoundDevice::Info Manager::FindDeviceInfo(SoundDevice::Manager::GlobalID id) const +//-------------------------------------------------------------------------------- +{ + if(id > m_SoundDevices.size()) + { + return SoundDevice::Info(); + } + return m_SoundDevices[id]; +} + + SoundDevice::Info Manager::FindDeviceInfo(SoundDevice::Identifier identifier) const //--------------------------------------------------------------------------------- { @@ -154,15 +194,12 @@ SoundDevice::Type ParseType(const SoundDevice::Identifier &identifier) //-------------------------------------------------------------------- { - for(int i = 0; i < TypeNUM_DEVTYPES; ++i) + std::vector<mpt::ustring> tmp = mpt::String::Split<mpt::ustring>(identifier, MPT_USTRING("_")); + if(tmp.size() == 0) { - const mpt::ustring api = SoundDevice::TypeToString(static_cast<SoundDevice::Type>(i)); - if(identifier.find(api) == 0) - { - return static_cast<SoundDevice::Type>(i); - } + return SoundDevice::Type(); } - return TypeINVALID; + return tmp[0]; } @@ -185,47 +222,31 @@ } } const SoundDevice::Type type = ParseType(identifier); - switch(type) + if(type == TypePORTAUDIO_WASAPI) { - case TypePORTAUDIO_WASAPI: - // WASAPI devices might change names if a different connector jack is used. - // In order to avoid defaulting to wave mapper in that case, - // just find the first WASAPI device. - for(std::vector<SoundDevice::Info>::const_iterator it = begin(); it != end(); ++it) + // WASAPI devices might change names if a different connector jack is used. + // In order to avoid defaulting to wave mapper in that case, + // just find the first WASAPI device. + for(std::vector<SoundDevice::Info>::const_iterator it = begin(); it != end(); ++it) + { + if((it->type == TypePORTAUDIO_WASAPI) && !IsDeviceUnavailable(it->GetIdentifier())) { - if((it->id.GetType() == TypePORTAUDIO_WASAPI) && !IsDeviceUnavailable(it->GetIdentifier())) - { - return *it; - } + return *it; } - // default to first device - return *begin(); - break; - case TypeWAVEOUT: - case TypeDSOUND: - case TypePORTAUDIO_WMME: - case TypePORTAUDIO_DS: - case TypeASIO: - case TypePORTAUDIO_WDMKS: - case TypePORTAUDIO_ASIO: - if(preferSameType) + } + } + if(preferSameType) + { + for(std::vector<SoundDevice::Info>::const_iterator it = begin(); it != end(); ++it) + { + if((it->type == type) && !IsDeviceUnavailable(it->GetIdentifier())) { - for(std::vector<SoundDevice::Info>::const_iterator it = begin(); it != end(); ++it) - { - if((it->id.GetType() == type) && !IsDeviceUnavailable(it->GetIdentifier())) - { - return *it; - } - } - } else - { - // default to first device - return *begin(); + return *it; } - break; + } } - // invalid - return SoundDevice::Info(); + // default to first device + return *begin(); } @@ -318,28 +339,23 @@ return nullptr; } SoundDevice::IBase *result = nullptr; - switch(info.id.GetType()) - { - case TypeWAVEOUT: result = new CWaveDevice(info); break; + if(info.type.empty()) { result = nullptr; } + if(info.type == TypeWAVEOUT) { result = new CWaveDevice(info); } #ifndef NO_DSOUND - case TypeDSOUND: result = new CDSoundDevice(info); break; + if(info.type == TypeDSOUND) { result = new CDSoundDevice(info); } #endif // NO_DSOUND #ifndef NO_ASIO - case TypeASIO: result = new CASIODevice(info); break; + if(info.type == TypeASIO) { result = new CASIODevice(info); } #endif // NO_ASIO #ifndef NO_PORTAUDIO - case TypePORTAUDIO_WASAPI: - case TypePORTAUDIO_WDMKS: - case TypePORTAUDIO_WMME: - case TypePORTAUDIO_DS: - case TypePORTAUDIO_ASIO: - if(IsComponentAvailable(m_PortAudio)) - { - result = new CPortaudioDevice(info); - } - break; + if(IsComponentAvailable(m_PortAudio)) + { + if(info.type == TypePORTAUDIO_WASAPI) { result = new CPortaudioDevice(info); } + if(info.type == TypePORTAUDIO_WDMKS) { result = new CPortaudioDevice(info); } + if(info.type == TypePORTAUDIO_WMME) { result = new CPortaudioDevice(info); } + if(info.type == TypePORTAUDIO_DS) { result = new CPortaudioDevice(info); } + } #endif // NO_PORTAUDIO - } if(!result) { return nullptr; @@ -370,6 +386,66 @@ } +namespace Legacy +{ +SoundDevice::Info FindDeviceInfo(SoundDevice::Manager &manager, SoundDevice::Legacy::ID id) +{ + if(manager.GetDeviceInfos().empty()) + { + return SoundDevice::Info(); + } + SoundDevice::Type type = SoundDevice::Type(); + switch(id & SoundDevice::Legacy::MaskType) + { + case SoundDevice::Legacy::TypeWAVEOUT: + type = SoundDevice::TypeWAVEOUT; + break; + case SoundDevice::Legacy::TypeDSOUND: + type = SoundDevice::TypeDSOUND; + break; + case SoundDevice::Legacy::TypeASIO: + type = SoundDevice::TypeASIO; + break; + case SoundDevice::Legacy::TypePORTAUDIO_WASAPI: + type = SoundDevice::TypePORTAUDIO_WASAPI; + break; + case SoundDevice::Legacy::TypePORTAUDIO_WDMKS: + type = SoundDevice::TypePORTAUDIO_WDMKS; + break; + case SoundDevice::Legacy::TypePORTAUDIO_WMME: + type = SoundDevice::TypePORTAUDIO_WMME; + break; + case SoundDevice::Legacy::TypePORTAUDIO_DS: + type = SoundDevice::TypePORTAUDIO_DS; + break; + } + if(type.empty()) + { // fallback to first device + return *manager.begin(); + } + std::size_t index = static_cast<uint8>(id & SoundDevice::Legacy::MaskIndex); + std::size_t seenDevicesOfDesiredType = 0; + for(std::vector<SoundDevice::Info>::const_iterator it = manager.begin(); it != manager.end(); ++it) + { + if(it->type == type) + { + if(seenDevicesOfDesiredType == index) + { + if(!it->IsValid()) + { // fallback to first device + return *manager.begin(); + } + return *it; + } + seenDevicesOfDesiredType++; + } + } + // default to first device + return *manager.begin(); +} +} + + } // namespace SoundDevice Modified: trunk/OpenMPT/sounddev/SoundDeviceManager.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceManager.h 2015-05-04 22:41:44 UTC (rev 5045) +++ trunk/OpenMPT/sounddev/SoundDeviceManager.h 2015-05-05 10:01:42 UTC (rev 5046) @@ -15,7 +15,10 @@ #include "../common/ComponentManager.h" +#include <map> +#include <vector> + OPENMPT_NAMESPACE_BEGIN @@ -32,6 +35,11 @@ class Manager //=========== { + +public: + + typedef std::size_t GlobalID; + private: const SoundDevice::AppInfo m_AppInfo; @@ -64,7 +72,9 @@ std::vector<SoundDevice::Info>::const_iterator end() const { return m_SoundDevices.end(); } const std::vector<SoundDevice::Info> & GetDeviceInfos() const { return m_SoundDevices; } - SoundDevice::Info FindDeviceInfo(SoundDevice::ID id) const; + SoundDevice::Manager::GlobalID GetGlobalID(SoundDevice::Identifier identifier) const; + + SoundDevice::Info FindDeviceInfo(SoundDevice::Manager::GlobalID id) const; SoundDevice::Info FindDeviceInfo(SoundDevice::Identifier identifier) const; SoundDevice::Info FindDeviceInfoBestMatch(SoundDevice::Identifier identifier, bool preferSameType); @@ -81,6 +91,12 @@ }; +namespace Legacy +{ +SoundDevice::Info FindDeviceInfo(SoundDevice::Manager &manager, SoundDevice::Legacy::ID id); +} + + } // namespace SoundDevice Modified: trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp 2015-05-04 22:41:44 UTC (rev 5045) +++ trunk/OpenMPT/sounddev/SoundDevicePortAudio.cpp 2015-05-05 10:01:42 UTC (rev 5046) @@ -42,7 +42,8 @@ : SoundDevice::Base(info) , m_StatisticPeriodFrames(0) { - m_HostApi = SndDevTypeToHostApi(info.id.GetType()); + m_DeviceIndex = ConvertStrTo<PaDeviceIndex>(GetDeviceInternalID()); + m_HostApiType = Pa_GetHostApiInfo(Pa_GetDeviceInfo(m_DeviceIndex)->hostApi)->type; MemsetZero(m_StreamParameters); m_Stream = 0; m_StreamInfo = 0; @@ -66,7 +67,7 @@ m_StreamInfo = 0; m_CurrentFrameBuffer = 0; m_CurrentFrameCount = 0; - m_StreamParameters.device = HostApiOutputIndexToGlobalDeviceIndex(GetDeviceIndex(), m_HostApi); + m_StreamParameters.device = m_DeviceIndex; if(m_StreamParameters.device == -1) return false; m_StreamParameters.channelCount = m_Settings.Channels; if(m_Settings.sampleFormat.IsFloat()) @@ -87,7 +88,7 @@ m_StreamParameters.suggestedLatency = m_Settings.Latency; m_StreamParameters.hostApiSpecificStreamInfo = NULL; unsigned long framesPerBuffer = static_cast<long>(m_Settings.UpdateInterval * m_Settings.Samplerate); - if(m_HostApi == Pa_HostApiTypeIdToHostApiIndex(paWASAPI)) + if(m_HostApiType == paWASAPI) { if(m_Settings.ExclusiveMode) { @@ -104,14 +105,14 @@ { m_Flags.NeedsClippedFloat = true; } - } else if(m_HostApi == Pa_HostApiTypeIdToHostApiIndex(paWDMKS)) + } else if(m_HostApiType == paWDMKS) { m_Flags.NeedsClippedFloat = false; framesPerBuffer = paFramesPerBufferUnspecified; // let portaudio choose - } else if(m_HostApi == Pa_HostApiTypeIdToHostApiIndex(paMME)) + } else if(m_HostApiType == paMME) { m_Flags.NeedsClippedFloat = mpt::Windows::Version::IsAtLeast(mpt::Windows::Version::WinVista); - } else if(m_HostApi == Pa_HostApiTypeIdToHostApiIndex(paDirectSound)) + } else if(m_HostApiType == paDirectSound) { m_Flags.NeedsClippedFloat = mpt::Windows::Version::IsAtLeast(mpt::Windows::Version::WinVista); } else @@ -227,25 +228,25 @@ caps.CanChannelMapping = false; caps.CanDriverPanel = false; caps.HasInternalDither = true; - const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(m_StreamParameters.device = HostApiOutputIndexToGlobalDeviceIndex(GetDeviceIndex(), m_HostApi)); + const PaDeviceInfo *deviceInfo = Pa_GetDeviceInfo(m_StreamParameters.device = m_DeviceIndex); if(deviceInfo) { caps.DefaultSettings.Latency = deviceInfo->defaultLowOutputLatency; } caps.DefaultSettings.sampleFormat = SampleFormatFloat32; - if(m_HostApi == Pa_HostApiTypeIdToHostApiIndex(paWASAPI)) + if(m_HostApiType == paWASAPI) { caps.CanExclusiveMode = true; caps.CanDriverPanel = true; caps.DefaultSettings.sampleFormat = SampleFormatFloat32; - } else if(m_HostApi == Pa_HostApiTypeIdToHostApiIndex(paWDMKS)) + } else if(m_HostApiType == paWDMKS) { caps.CanUpdateInterval = false; caps.DefaultSettings.sampleFormat = SampleFormatInt32; - } else if(m_HostApi == Pa_HostApiTypeIdToHostApiIndex(paDirectSound)) + } else if(m_HostApiType == paDirectSound) { caps.DefaultSettings.sampleFormat = SampleFormatInt16; - } else if(m_HostApi == Pa_HostApiTypeIdToHostApiIndex(paMME)) + } else if(m_HostApiType == paMME) { if(mpt::Windows::Version::IsWine()) { @@ -257,7 +258,7 @@ { caps.DefaultSettings.sampleFormat = SampleFormatInt16; } - } else if(m_HostApi == Pa_HostApiTypeIdToHostApiIndex(paASIO)) + } else if(m_HostApiType == paASIO) { caps.DefaultSettings.sampleFormat = SampleFormatInt32; } @@ -269,7 +270,7 @@ //------------------------------------------------------------------------------------------------------- { SoundDevice::DynamicCaps caps; - PaDeviceIndex device = HostApiOutputIndexToGlobalDeviceIndex(GetDeviceIndex(), m_HostApi); + PaDeviceIndex device = m_DeviceIndex; if(device == -1) { return caps; @@ -283,7 +284,7 @@ StreamParameters.sampleFormat = paInt16; StreamParameters.suggestedLatency = 0.0; StreamParameters.hostApiSpecificStreamInfo = NULL; - if((m_HostApi == Pa_HostApiTypeIdToHostApiIndex(paWASAPI)) && m_Settings.ExclusiveMode) + if((m_HostApiType == paWASAPI) && m_Settings.ExclusiveMode) { MemsetZero(m_WasapiStreamInfo); m_WasapiStreamInfo.size = sizeof(PaWasapiStreamInfo); @@ -305,7 +306,7 @@ bool CPortaudioDevice::OpenDriverSettings() //----------------------------------------- { - if(m_HostApi != Pa_HostApiTypeIdToHostApiIndex(paWASAPI)) + if(m_HostApiType != paWASAPI) { return false; } @@ -334,16 +335,16 @@ MPT_UNREFERENCED_PARAMETER(input); MPT_UNREFERENCED_PARAMETER(statusFlags); if(!output) return paAbort; - if(Pa_GetHostApiInfo(m_HostApi)->type == paWDMKS) + if(m_HostApiType == paWDMKS) { // For WDM-KS, timeInfo->outputBufferDacTime seems to contain bogus values. // Work-around it by using the slightly less accurate per-stream latency estimation. m_CurrentRealLatency = m_StreamInfo->outputLatency; - } else if(Pa_GetHostApiInfo(m_HostApi)->type == paWASAPI) + } else if(m_HostApiType == paWASAPI) { // PortAudio latency calculation appears to miss the current period or chunk for WASAPI. Compensate it. m_CurrentRealLatency = timeInfo->outputBufferDacTime - timeInfo->currentTime + ((double)frameCount / (double)m_Settings.Samplerate); - } else if(Pa_GetHostApiInfo(m_HostApi)->type == paDirectSound) + } else if(m_HostApiType == paDirectSound) { // PortAudio latency calculation appears to miss the buffering latency. // The current chunk, however, appears to be compensated for. @@ -375,111 +376,82 @@ } -PaDeviceIndex CPortaudioDevice::HostApiOutputIndexToGlobalDeviceIndex(int hostapioutputdeviceindex, PaHostApiIndex hostapi) -//------------------------------------------------------------------------------------------------------------------- +std::vector<SoundDevice::Info> CPortaudioDevice::EnumerateDevices() +//----------------------------------------------------------------- { - if(hostapi < 0) - return -1; - if(hostapi >= Pa_GetHostApiCount()) - return -1; - if(!Pa_GetHostApiInfo(hostapi)) - return -1; - if(hostapioutputdeviceindex < 0) - return -1; - if(hostapioutputdeviceindex >= Pa_GetHostApiInfo(hostapi)->deviceCount) - return -1; - int dev = hostapioutputdeviceindex; - for(int hostapideviceindex=0; hostapideviceindex<Pa_GetHostApiInfo(hostapi)->deviceCount; hostapideviceindex++) + std::vector<SoundDevice::Info> devices; + for(PaDeviceIndex dev = 0; dev < Pa_GetDeviceCount(); ++dev) { - if(!Pa_GetDeviceInfo(Pa_HostApiDeviceIndexToDeviceIndex(hostapi, hostapideviceindex))) + if(!Pa_GetDeviceInfo(dev)) { - dev++; // skip this device continue; } - if(Pa_GetDeviceInfo(Pa_HostApiDeviceIndexToDeviceIndex(hostapi, hostapideviceindex))->maxOutputChannels == 0) + if(Pa_GetDeviceInfo(dev)->hostApi < 0) { - dev++; // skip this device continue; } - if(dev == hostapideviceindex) + if(!Pa_GetHostApiInfo(Pa_GetDeviceInfo(dev)->hostApi)) { - break; + continue; } - } - if(dev >= Pa_GetHostApiInfo(hostapi)->deviceCount) - return -1; - return Pa_HostApiDeviceIndexToDeviceIndex(hostapi, dev); -} - - -SoundDevice::Type CPortaudioDevice::HostApiToSndDevType(PaHostApiIndex hostapi) -//--------------------------------------------------------------------------- -{ - if(hostapi == Pa_HostApiTypeIdToHostApiIndex(paWASAPI)) return TypePORTAUDIO_WASAPI; - if(hostapi == Pa_HostApiTypeIdToHostApiIndex(paWDMKS)) return TypePORTAUDIO_WDMKS; - if(hostapi == Pa_HostApiTypeIdToHostApiIndex(paMME)) return TypePORTAUDIO_WMME; - if(hostapi == Pa_HostApiTypeIdToHostApiIndex(paDirectSound)) return TypePORTAUDIO_DS; - if(hostapi == Pa_HostApiTypeIdToHostApiIndex(paASIO)) return TypePORTAUDIO_ASIO; - return TypeINVALID; -} - - -PaHostApiIndex CPortaudioDevice::SndDevTypeToHostApi(SoundDevice::Type snddevtype) -//------------------------------------------------------------------------------ -{ - if(snddevtype == TypePORTAUDIO_WASAPI) return Pa_HostApiTypeIdToHostApiIndex(paWASAPI); - if(snddevtype == TypePORTAUDIO_WDMKS) return Pa_HostApiTypeIdToHostApiIndex(paWDMKS); - if(snddevtype == TypePORTAUDIO_WMME) return Pa_HostApiTypeIdToHostApiIndex(paMME); - if(snddevtype == TypePORTAUDIO_DS) return Pa_HostApiTypeIdToHostApiIndex(paDirectSound); - if(snddevtype == TypePORTAUDIO_ASIO) return Pa_HostApiTypeIdToHostApiIndex(paASIO); - return paInDevelopment; -} - - -mpt::ustring CPortaudioDevice::HostApiToString(PaHostApiIndex hostapi) -//-------------------------------------------------------------------- -{ - SoundDevice::Type type = HostApiToSndDevType(hostapi); - if(type == TypeINVALID) - { - return MPT_USTRING("PortAudio"); - } - return SoundDevice::TypeToString(type); -} - - -bool CPortaudioDevice::EnumerateDevices(SoundDevice::Info &result, SoundDevice::Index index, PaHostApiIndex hostapi) -//-------------------------------------------------------------------------------------------------------------- -{ - result = SoundDevice::Info(); - PaDeviceIndex dev = HostApiOutputIndexToGlobalDeviceIndex(index, hostapi); - if(dev == -1) - return false; - if(!Pa_GetDeviceInfo(dev)) - return false; - result.id = SoundDevice::ID(HostApiToSndDevType(hostapi), index); - result.name = mpt::ToUnicode(mpt::CharsetUTF8, Pa_GetDeviceInfo(dev)->name); - result.apiName = HostApiToString(Pa_GetDeviceInfo(dev)->hostApi); - result.isDefault = (Pa_GetHostApiInfo(Pa_GetDeviceInfo(dev)->hostApi)->defaultOutputDevice == (PaDeviceIndex)dev); - PALOG(mpt::String::Print("PortAudio: %1, %2, %3, %4", result.id.GetIdRaw(), mpt::ToLocale(result.name), mpt::ToLocale(result.apiName), result.isDefault)); - PALOG(mpt::String::Print(" low : %1", Pa_GetDeviceInfo(dev)->defaultLowOutputLatency)); - PALOG(mpt::String::Print(" high : %1", Pa_GetDeviceInfo(dev)->defaultHighOutputLatency)); - return true; -} - - -std::vector<SoundDevice::Info> CPortaudioDevice::EnumerateDevices(SoundDevice::Type type) -//----------------------------------------------------------------------------------- -{ - std::vector<SoundDevice::Info> devices; - for(SoundDevice::Index index = 0; ; ++index) - { - SoundDevice::Info info; - if(!EnumerateDevices(info, index, CPortaudioDevice::SndDevTypeToHostApi(type))) + if(!Pa_GetDeviceInfo(dev)->name) { - break; + continue; } - devices.push_back(info); + if(!Pa_GetHostApiInfo(Pa_GetDeviceInfo(dev)->hostApi)->name) + { + continue; + } + if(Pa_GetDeviceInfo(dev)->maxOutputChannels <= 0) + { + continue; + } + SoundDevice::Info result = SoundDevice::Info(); + switch((Pa_GetHostApiInfo(Pa_GetDeviceInfo(dev)->hostApi)->type)) + { + case paWASAPI: + result.type = TypePORTAUDIO_WASAPI; + break; + case paWDMKS: + result.type = TypePORTAUDIO_WDMKS; + break; + case paMME: + result.type = TypePORTAUDIO_WMME; + break; + case paDirectSound: + result.type = TypePORTAUDIO_DS; + break; + default: + result.type = MPT_USTRING("PortAudio") + MPT_USTRING("-") + mpt::ufmt::dec(static_cast<int>(Pa_GetHostApiInfo(Pa_GetDeviceInfo(dev)->hostApi)->type)); + break; + } + result.internalID = mpt::ufmt::dec(dev); + result.name = mpt::ToUnicode(mpt::CharsetUTF8, Pa_GetDeviceInfo(dev)->name); + switch(Pa_GetHostApiInfo(Pa_GetDeviceInfo(dev)->hostApi)->type) + { + case paWASAPI: + result.apiName = MPT_USTRING("WASAPI"); + break; + case paWDMKS: + if(mpt::Windows::Version::IsAtLeast(mpt::Windows::Version::WinVista)) + { + result.apiName = MPT_USTRING("WaveRT"); + } else + { + result.apiName = MPT_USTRING("WDM-KS"); + } + break; + default: + result.apiName = mpt::ToUnicode(mpt::CharsetUTF8, Pa_GetHostApiInfo(Pa_GetDeviceInfo(dev)->hostApi)->name); + break; + } + result.apiPath.push_back(MPT_USTRING("PortAudio")); + result.isDefault = (Pa_GetHostApiInfo(Pa_GetDeviceInfo(dev)->hostApi)->defaultOutputDevice == (PaDeviceIndex)dev); + result.useNameAsIdentifier = true; + PALOG(mpt::String::Print("PortAudio: %1, %2, %3, %4", result.id.GetIdRaw(), mpt::ToLocale(result.name), mpt::ToLocale(result.apiName), result.isDefault)); + PALOG(mpt::String::Print(" low : %1", Pa_GetDeviceInfo(dev)->defaultLowOutputLatency)); + PALOG(mpt::String::Print(" high : %1", Pa_GetDeviceInfo(dev)->defaultHighOutputLatency)); + devices.push_back(result); } return devices; } Modified: trunk/OpenMPT/sounddev/SoundDevicePortAudio.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDevicePortAudio.h 2015-05-04 22:41:44 UTC (rev 5045) +++ trunk/OpenMPT/sounddev/SoundDevicePortAudio.h 2015-05-05 10:01:42 UTC (rev 5046) @@ -35,7 +35,8 @@ //========================================= { protected: - PaHostApiIndex m_HostApi; + PaDeviceIndex m_DeviceIndex; + PaHostApiTypeId m_HostApiType; PaStreamParameters m_StreamParameters; PaWasapiStreamInfo m_WasapiStreamInfo; PaStream * m_Stream; @@ -81,17 +82,8 @@ void *userData ); - static mpt::ustring HostApiToString(PaHostApiIndex hostapi); + static std::vector<SoundDevice::Info> EnumerateDevices(); - static PaDeviceIndex HostApiOutputIndexToGlobalDeviceIndex(int hostapioutputdeviceindex, PaHostApiIndex hostapi); - static SoundDevice::Type HostApiToSndDevType(PaHostApiIndex hostapi); - static PaHostApiIndex SndDevTypeToHostApi(SoundDevice::Type snddevtype); - - static std::vector<SoundDevice::Info> EnumerateDevices(SoundDevice::Type type); - -private: - static bool EnumerateDevices(SoundDevice::Info &result, SoundDevice::Index index, PaHostApiIndex hostapi); - }; Modified: trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp 2015-05-04 22:41:44 UTC (rev 5045) +++ trunk/OpenMPT/sounddev/SoundDeviceWaveout.cpp 2015-05-05 10:01:42 UTC (rev 5046) @@ -61,6 +61,13 @@ } +int CWaveDevice::GetDeviceIndex() const +//------------------------------------- +{ + return ConvertStrTo<int>(GetDeviceInternalID()); +} + + SoundDevice::Caps CWaveDevice::InternalGetDeviceCaps() //-------------------------------------------------- { @@ -355,13 +362,11 @@ UINT numDevs = waveOutGetNumDevs(); for(UINT index = 0; index <= numDevs; ++index) { - if(!SoundDevice::IndexIsValid(index)) - { - break; - } SoundDevice::Info info; - info.id = SoundDevice::ID(TypeWAVEOUT, static_cast<SoundDevice::Index>(index)); - info.apiName = SoundDevice::TypeToString(TypeWAVEOUT); + info.type = TypeWAVEOUT; + info.internalID = mpt::ufmt::dec(index); + info.apiName = MPT_USTRING("WaveOut"); + info.useNameAsIdentifier = true; WAVEOUTCAPSW woc; MemsetZero(woc); if(index == 0) Modified: trunk/OpenMPT/sounddev/SoundDeviceWaveout.h =================================================================== --- trunk/OpenMPT/sounddev/SoundDeviceWaveout.h 2015-05-04 22:41:44 UTC (rev 5045) +++ trunk/OpenMPT/sounddev/SoundDeviceWaveout.h 2015-05-05 10:01:42 UTC (rev 5046) @@ -78,8 +78,11 @@ SoundDevice::DynamicCaps GetDeviceDynamicCaps(const std::vector<uint32> &baseSampleRates); private: + void HandleWaveoutDone(); + int GetDeviceIndex() const; + public: static void CALLBACK WaveOutCallBack(HWAVEOUT, UINT uMsg, DWORD_PTR, DWORD_PTR dw1, DWORD_PTR dw2); static std::vector<SoundDevice::Info> EnumerateDevices(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |