diff --git a/CMakeLists.txt b/CMakeLists.txt index e67bfc6..93ea536 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,179 +40,179 @@ endif () set(CMAKE_CXX_STANDARD 20) set(EHS_SOURCES - src/EHS.cpp include/ehs/EHS.h - src/Type.cpp include/ehs/Type.h - src/BaseObj.cpp include/ehs/BaseObj.h - src/GC.cpp include/ehs/GC.h - src/Log.cpp include/ehs/Log.h - src/URI.cpp include/ehs/URI.h - src/Math.cpp include/ehs/Math.h - src/Color4.cpp include/ehs/Color4.h - src/Color3.cpp include/ehs/Color3.h - src/Version.cpp include/ehs/Version.h - src/Base64.cpp include/ehs/Base64.h - src/Data.cpp include/ehs/Data.h - src/Range.cpp include/ehs/Range.h - src/Util.cpp include/ehs/Util.h - src/Task.cpp include/ehs/Task.h - src/DataType.cpp include/ehs/DataType.h - include/ehs/Anchor.h - include/ehs/Dock.h - include/ehs/HashMap.h - include/ehs/HRNG.h - include/ehs/Link.h - include/ehs/LinkedList.h - include/ehs/Mat2.h - include/ehs/Mat3.h - include/ehs/Mat4.h - include/ehs/PRNG.h - include/ehs/Quat.h - include/ehs/Rect.h - include/ehs/Str.h - include/ehs/Types.h - include/ehs/UTF.h - include/ehs/Vec2.h - include/ehs/Vec3.h - include/ehs/Vec4.h - include/ehs/Serializer.h - include/ehs/Array.h - include/ehs/Vector.h - include/ehs/SArray.h - src/PtrData.cpp include/ehs/PtrData.h - include/ehs/UniPtr.h - include/ehs/ShdPtr.h - include/ehs/WkPtr.h + src/EHS.cpp include/ehs/EHS.h + src/Type.cpp include/ehs/Type.h + src/BaseObj.cpp include/ehs/BaseObj.h + src/GC.cpp include/ehs/GC.h + src/Log.cpp include/ehs/Log.h + src/URI.cpp include/ehs/URI.h + src/Math.cpp include/ehs/Math.h + src/Color4.cpp include/ehs/Color4.h + src/Color3.cpp include/ehs/Color3.h + src/Version.cpp include/ehs/Version.h + src/Base64.cpp include/ehs/Base64.h + src/Data.cpp include/ehs/Data.h + src/Range.cpp include/ehs/Range.h + src/Util.cpp include/ehs/Util.h + src/Task.cpp include/ehs/Task.h + src/DataType.cpp include/ehs/DataType.h + include/ehs/Anchor.h + include/ehs/Dock.h + include/ehs/HashMap.h + include/ehs/HRNG.h + include/ehs/Link.h + include/ehs/LinkedList.h + include/ehs/Mat2.h + include/ehs/Mat3.h + include/ehs/Mat4.h + include/ehs/PRNG.h + include/ehs/Quat.h + include/ehs/Rect.h + include/ehs/Str.h + include/ehs/Types.h + include/ehs/UTF.h + include/ehs/Vec2.h + include/ehs/Vec3.h + include/ehs/Vec4.h + include/ehs/Serializer.h + include/ehs/Array.h + include/ehs/Vector.h + include/ehs/SArray.h + src/PtrData.cpp include/ehs/PtrData.h + include/ehs/UniPtr.h + include/ehs/ShdPtr.h + include/ehs/WkPtr.h - src/db/DbVarTmpl.cpp include/ehs/db/DbVarTmpl.h + src/db/DbVarTmpl.cpp include/ehs/db/DbVarTmpl.h - src/system/CPU.cpp include/ehs/system/CPU.h - src/system/Thread.cpp include/ehs/system/Thread.h - src/system/BaseMutex.cpp include/ehs/system/BaseMutex.h - src/system/BaseSemaphore.cpp include/ehs/system/BaseSemaphore.h - src/system/BaseSystem.cpp include/ehs/system/BaseSystem.h - src/system/BaseOpen.cpp include/ehs/system/BaseOpen.h - include/ehs/system/Architecture.h - include/ehs/system/Mutex.h - include/ehs/system/Open.h - include/ehs/system/OS.h - include/ehs/system/Semaphore.h - include/ehs/system/System.h + src/system/CPU.cpp include/ehs/system/CPU.h + src/system/Thread.cpp include/ehs/system/Thread.h + src/system/BaseMutex.cpp include/ehs/system/BaseMutex.h + src/system/BaseSemaphore.cpp include/ehs/system/BaseSemaphore.h + src/system/BaseSystem.cpp include/ehs/system/BaseSystem.h + src/system/BaseOpen.cpp include/ehs/system/BaseOpen.h + include/ehs/system/Architecture.h + include/ehs/system/Mutex.h + include/ehs/system/Open.h + include/ehs/system/OS.h + include/ehs/system/Semaphore.h + include/ehs/system/System.h - src/json/Json.cpp include/ehs/json/Json.h - src/json/JsonBase.cpp include/ehs/json/JsonBase.h - src/json/JsonNum.cpp include/ehs/json/JsonNum.h - src/json/JsonBool.cpp include/ehs/json/JsonBool.h - src/json/JsonStr.cpp include/ehs/json/JsonStr.h - src/json/JsonObj.cpp include/ehs/json/JsonObj.h - src/json/JsonArray.cpp include/ehs/json/JsonArray.h - src/json/JsonVar.cpp include/ehs/json/JsonVar.h + src/json/Json.cpp include/ehs/json/Json.h + src/json/JsonBase.cpp include/ehs/json/JsonBase.h + src/json/JsonNum.cpp include/ehs/json/JsonNum.h + src/json/JsonBool.cpp include/ehs/json/JsonBool.h + src/json/JsonStr.cpp include/ehs/json/JsonStr.h + src/json/JsonObj.cpp include/ehs/json/JsonObj.h + src/json/JsonArray.cpp include/ehs/json/JsonArray.h + src/json/JsonVar.cpp include/ehs/json/JsonVar.h - src/io/Resource.cpp include/ehs/io/Resource.h - src/io/Console.cpp include/ehs/io/Console.h - src/io/RIFF_Chunk.cpp include/ehs/io/RIFF_Chunk.h - src/io/RIFF.cpp include/ehs/io/RIFF.h - src/io/BaseWindow.cpp include/ehs/io/BaseWindow.h - src/io/BaseFile.cpp include/ehs/io/BaseFile.h - src/io/Glyph.cpp include/ehs/io/Glyph.h - src/io/FontAtlas.cpp include/ehs/io/FontAtlas.h - src/io/BaseFileMonitor.cpp include/ehs/io/BaseFileMonitor.h - include/ehs/io/COM.h - include/ehs/io/File.h - include/ehs/io/FileMonitor.h - include/ehs/io/Window.h + src/io/Resource.cpp include/ehs/io/Resource.h + src/io/Console.cpp include/ehs/io/Console.h + src/io/RIFF_Chunk.cpp include/ehs/io/RIFF_Chunk.h + src/io/RIFF.cpp include/ehs/io/RIFF.h + src/io/BaseWindow.cpp include/ehs/io/BaseWindow.h + src/io/BaseFile.cpp include/ehs/io/BaseFile.h + src/io/Glyph.cpp include/ehs/io/Glyph.h + src/io/FontAtlas.cpp include/ehs/io/FontAtlas.h + src/io/BaseFileMonitor.cpp include/ehs/io/BaseFileMonitor.h + include/ehs/io/COM.h + include/ehs/io/File.h + include/ehs/io/FileMonitor.h + include/ehs/io/Window.h - src/io/socket/Request.cpp include/ehs/io/socket/Request.h - src/io/socket/Response.cpp include/ehs/io/socket/Response.h - src/io/socket/BaseDNS.cpp include/ehs/io/socket/BaseDNS.h - src/io/socket/BaseUDP.cpp include/ehs/io/socket/BaseUDP.h - src/io/socket/BaseTCP.cpp include/ehs/io/socket/BaseTCP.h - src/io/socket/SSL.cpp include/ehs/io/socket/SSL.h + src/io/socket/Request.cpp include/ehs/io/socket/Request.h + src/io/socket/Response.cpp include/ehs/io/socket/Response.h + src/io/socket/BaseDNS.cpp include/ehs/io/socket/BaseDNS.h + src/io/socket/BaseUDP.cpp include/ehs/io/socket/BaseUDP.h + src/io/socket/BaseTCP.cpp include/ehs/io/socket/BaseTCP.h + src/io/socket/SSL.cpp include/ehs/io/socket/SSL.h - src/io/socket/rest/Twitch.cpp include/ehs/io/socket/rest/Twitch.h - src/io/socket/rest/TwitchChat.cpp include/ehs/io/socket/rest/TwitchChat.h - src/io/socket/rest/Spotify.cpp include/ehs/io/socket/rest/Spotify.h - include/ehs/io/socket/Socket.h - include/ehs/io/socket/TCP.h - include/ehs/io/socket/UDP.h - include/ehs/io/socket/DNS.h + src/io/socket/rest/Twitch.cpp include/ehs/io/socket/rest/Twitch.h + src/io/socket/rest/TwitchChat.cpp include/ehs/io/socket/rest/TwitchChat.h + src/io/socket/rest/Spotify.cpp include/ehs/io/socket/rest/Spotify.h + include/ehs/io/socket/Socket.h + include/ehs/io/socket/TCP.h + include/ehs/io/socket/UDP.h + include/ehs/io/socket/DNS.h - src/io/audio/Audio.cpp include/ehs/io/audio/Audio.h - src/io/audio/BaseAudioDevice.cpp include/ehs/io/audio/BaseAudioDevice.h - src/io/audio/AudioCodec.cpp include/ehs/io/audio/AudioCodec.h - include/ehs/io/audio/AudioDevice.h + src/io/audio/Audio.cpp include/ehs/io/audio/Audio.h + src/io/audio/BaseAudioDevice.cpp include/ehs/io/audio/BaseAudioDevice.h + src/io/audio/AudioCodec.cpp include/ehs/io/audio/AudioCodec.h + include/ehs/io/audio/AudioDevice.h - src/io/img/PNG.cpp include/ehs/io/img/PNG.h - src/io/img/Img.cpp include/ehs/io/img/Img.h - src/io/img/PNG_Chunk.cpp include/ehs/io/img/PNG_Chunk.h - src/io/img/ImgCodec.cpp include/ehs/io/img/ImgCodec.h + src/io/img/PNG.cpp include/ehs/io/img/PNG.h + src/io/img/Img.cpp include/ehs/io/img/Img.h + src/io/img/PNG_Chunk.cpp include/ehs/io/img/PNG_Chunk.h + src/io/img/ImgCodec.cpp include/ehs/io/img/ImgCodec.h - include/ehs/io/mdl/Vertex.h - src/io/model/Mesh.cpp include/ehs/io/mdl/Mesh.h - src/io/model/Bone.cpp include/ehs/io/mdl/Bone.h - src/io/model/Mdl.cpp include/ehs/io/mdl/Mdl.h - src/io/model/Animation.cpp include/ehs/io/mdl/Animation.h - src/io/model/AnimBone.cpp include/ehs/io/mdl/AnimBone.h - src/io/model/KeyFrame.cpp include/ehs/io/mdl/KeyFrame.h - src/io/model/PropertyChange.cpp include/ehs/io/mdl/PropertyChange.h + include/ehs/io/mdl/Vertex.h + src/io/model/Mesh.cpp include/ehs/io/mdl/Mesh.h + src/io/model/Bone.cpp include/ehs/io/mdl/Bone.h + src/io/model/Mdl.cpp include/ehs/io/mdl/Mdl.h + src/io/model/Animation.cpp include/ehs/io/mdl/Animation.h + src/io/model/AnimBone.cpp include/ehs/io/mdl/AnimBone.h + src/io/model/KeyFrame.cpp include/ehs/io/mdl/KeyFrame.h + src/io/model/PropertyChange.cpp include/ehs/io/mdl/PropertyChange.h - src/io/hid/ButtonState.cpp include/ehs/io/hid/ButtonState.h - src/io/hid/Button.cpp include/ehs/io/hid/Button.h - src/io/hid/Mouse.cpp include/ehs/io/hid/Mouse.h - src/io/hid/Keyboard.cpp include/ehs/io/hid/Keyboard.h - src/io/hid/HID.cpp include/ehs/io/hid/HID.h - src/io/hid/InputHandler.cpp include/ehs/io/hid/InputHandler.h - src/io/hid/Input.cpp include/ehs/io/hid/Input.h - src/io/model/MdlCodec.cpp - include/ehs/io/mdl/MdlCodec.h - include/ehs/io/UsbBase.h - src/io/UsbBase.cpp - include/ehs/db/DbTable.h - include/ehs/db/DbObject.h - include/ehs/db/DbVar.h - src/db/DbVar.cpp - include/ehs/db/Database.h - src/db/DbObject.cpp - src/db/Database.cpp - src/db/Database.cpp - src/db/DbTable.cpp - include/ehs/io/BaseDirectory.h - src/io/BaseDirectory.cpp - include/ehs/io/Directory.h + src/io/hid/ButtonState.cpp include/ehs/io/hid/ButtonState.h + src/io/hid/Button.cpp include/ehs/io/hid/Button.h + src/io/hid/Mouse.cpp include/ehs/io/hid/Mouse.h + src/io/hid/Keyboard.cpp include/ehs/io/hid/Keyboard.h + src/io/hid/HID.cpp include/ehs/io/hid/HID.h + src/io/hid/InputHandler.cpp include/ehs/io/hid/InputHandler.h + src/io/hid/Input.cpp include/ehs/io/hid/Input.h + src/io/model/MdlCodec.cpp + include/ehs/io/mdl/MdlCodec.h + include/ehs/io/UsbBase.h + src/io/UsbBase.cpp + include/ehs/db/DbTable.h + include/ehs/db/DbObject.h + include/ehs/db/DbVar.h + src/db/DbVar.cpp + include/ehs/db/Database.h + src/db/DbObject.cpp + src/db/Database.cpp + src/db/Database.cpp + src/db/DbTable.cpp + include/ehs/io/BaseDirectory.h + src/io/BaseDirectory.cpp + include/ehs/io/Directory.h ) if (IS_OS_WINDOWS) list(APPEND EHS_SOURCES - src/io/socket/UDP_W32.cpp include/ehs/io/socket/UDP_W32.h - src/io/socket/TCP_W32.cpp include/ehs/io/socket/TCP_W32.h - src/io/socket/DNS_W32.cpp include/ehs/io/socket/DNS_W32.h - src/system/Semaphore_W32.cpp include/ehs/system/Semaphore_W32.h - src/system/System_W32.cpp include/ehs/system/System_W32.h - src/system/Mutex_W32.cpp include/ehs/system/Mutex_W32.h - src/system/Open_W32.cpp include/ehs/system/Open_W32.h - src/io/audio/audioDevice_W32.cpp include/ehs/io/audio/audioDevice_W32.h - src/io/File_W32.cpp include/ehs/io/File_W32.h - src/io/FileMonitor_W32.cpp include/ehs/io/FileMonitor_W32.h - src/io/Window_W32.cpp include/ehs/io/Window_W32.h - src/io/COM.cpp include/ehs/io/COM.h - src/system/CPU_MSVC_AMD64.asm src/HRNG_MSVC.asm src/Math_MSVC_AMD64.asm - src/io/Directory_W32.cpp include/ehs/io/Directory_W32.h + src/io/socket/UDP_W32.cpp include/ehs/io/socket/UDP_W32.h + src/io/socket/TCP_W32.cpp include/ehs/io/socket/TCP_W32.h + src/io/socket/DNS_W32.cpp include/ehs/io/socket/DNS_W32.h + src/system/Semaphore_W32.cpp include/ehs/system/Semaphore_W32.h + src/system/System_W32.cpp include/ehs/system/System_W32.h + src/system/Mutex_W32.cpp include/ehs/system/Mutex_W32.h + src/system/Open_W32.cpp include/ehs/system/Open_W32.h + src/io/audio/audioDevice_W32.cpp include/ehs/io/audio/audioDevice_W32.h + src/io/File_W32.cpp include/ehs/io/File_W32.h + src/io/FileMonitor_W32.cpp include/ehs/io/FileMonitor_W32.h + src/io/Window_W32.cpp include/ehs/io/Window_W32.h + src/io/COM.cpp include/ehs/io/COM.h + src/system/CPU_MSVC_AMD64.asm src/HRNG_MSVC.asm src/Math_MSVC_AMD64.asm + src/io/Directory_W32.cpp include/ehs/io/Directory_W32.h ) elseif (IS_OS_LINUX) list(APPEND EHS_SOURCES - src/io/socket/UDP_BSD.cpp include/ehs/io/socket/UDP_BSD.h - src/io/socket/TCP_BSD.cpp include/ehs/io/socket/TCP_BSD.h - src/io/socket/DNS_LNX.cpp include/ehs/io/socket/DNS_LNX.h - src/system/Semaphore_P.cpp include/ehs/system/Semaphore_P.h - src/system/System_LNX.cpp include/ehs/system/System_LNX.h - src/system/Open_UNX.cpp include/ehs/system/Open_UNX.h - src/io/File_UNX.cpp include/ehs/io/File_UNX.h - src/io/FileMonitor_UNX.cpp include/ehs/io/FileMonitor_UNX.h - src/system/Mutex_PT.cpp include/ehs/system/Mutex_PT.h - src/io/audio/AudioDevice_ALSA.cpp include/ehs/io/audio/AudioDevice_ALSA.h - src/system/FileSystem.cpp include/ehs/system/FileSystem.h - src/system/User.cpp include/ehs/system/User.h - src/io/Directory_LNX.cpp include/ehs/io/Directory_LNX.h - src/io/Usb_LNX.cpp include/ehs/io/Usb_LNX.h + src/io/socket/UDP_BSD.cpp include/ehs/io/socket/UDP_BSD.h + src/io/socket/TCP_BSD.cpp include/ehs/io/socket/TCP_BSD.h + src/io/socket/DNS_LNX.cpp include/ehs/io/socket/DNS_LNX.h + src/system/Semaphore_P.cpp include/ehs/system/Semaphore_P.h + src/system/System_LNX.cpp include/ehs/system/System_LNX.h + src/system/Open_UNX.cpp include/ehs/system/Open_UNX.h + src/io/File_UNX.cpp include/ehs/io/File_UNX.h + src/io/FileMonitor_UNX.cpp include/ehs/io/FileMonitor_UNX.h + src/system/Mutex_PT.cpp include/ehs/system/Mutex_PT.h + src/io/audio/AudioDevice_PW.cpp include/ehs/io/audio/AudioDevice_PW.h + src/system/FileSystem.cpp include/ehs/system/FileSystem.h + src/system/User.cpp include/ehs/system/User.h + src/io/Directory_LNX.cpp include/ehs/io/Directory_LNX.h + src/io/Usb_LNX.cpp include/ehs/io/Usb_LNX.h ) #set(LINUX_WINDOW_SYSTEM "Wayland" CACHE STRING "Linux Window System") diff --git a/include/ehs/io/audio/AudioDevice.h b/include/ehs/io/audio/AudioDevice.h index f570427..13b34bb 100644 --- a/include/ehs/io/audio/AudioDevice.h +++ b/include/ehs/io/audio/AudioDevice.h @@ -5,5 +5,5 @@ #if defined(EHS_OS_WINDOWS) #include "AudioDevice_W32.h" #elif defined(EHS_OS_LINUX) -#include "AudioDevice_ALSA.h" -#endif \ No newline at end of file +#include "AudioDevice_PW.h" +#endif diff --git a/include/ehs/io/audio/AudioDevice_ALSA.h b/include/ehs/io/audio/AudioDevice_PW.h similarity index 61% rename from include/ehs/io/audio/AudioDevice_ALSA.h rename to include/ehs/io/audio/AudioDevice_PW.h index 0f4d0cd..f94bddd 100644 --- a/include/ehs/io/audio/AudioDevice_ALSA.h +++ b/include/ehs/io/audio/AudioDevice_PW.h @@ -3,16 +3,15 @@ #include "ehs/EHS.h" #include "BaseAudioDevice.h" -#include #include #include #include #include -#include +#include namespace ehs { - class EHS_LIB_IO AudioDevice : public BaseAudioDevice + class EHS_LIB_IO AudioDevice final : public BaseAudioDevice { private: static Array devices; @@ -24,11 +23,14 @@ namespace ehs pw_loop *loop; pw_context *context; pw_core *core; - pw_stream *stream; + pw_stream *input; + pw_stream *output; - static void RegistryEventGlobal(void *user_data, UInt_32 id, UInt_32 permissions, const char *type, UInt_32 version, const spa_dict *props); + static void RegistryEventGlobal(void *data, UInt_32 id, UInt_32 permissions, const char *type, UInt_32 version, const spa_dict *props); - static void RegistryEventGlobalRemove(void *user_data, UInt_32 id); + static void RegistryEventGlobalRemove(void *data, UInt_32 id); + + static void OnParamChanged(void *data, UInt_32 id, const spa_pod *param); public: ~AudioDevice() override; @@ -43,18 +45,23 @@ namespace ehs AudioDevice& operator=(const AudioDevice& device); - void Release() override; - void OpenStream() override; void CloseStream() override; - UInt_64 SendStream(void *data, UInt_64 size) override; + UInt_64 SendStream(const void *data, UInt_64 size) override; + + UInt_64 ReceiveStream(void *data, UInt_64 size) override; + + bool IsStreaming() const override; bool IsValid() const override; static AudioDevice GetDefault(AudioDeviceType type); static Array Get(AudioDeviceType type, AudioDeviceState state); + + private: + Str_8 GetCategory() const; }; } diff --git a/include/ehs/io/audio/AudioDevice_W32.h b/include/ehs/io/audio/AudioDevice_W32.h index f5bcf56..889b99b 100644 --- a/include/ehs/io/audio/AudioDevice_W32.h +++ b/include/ehs/io/audio/AudioDevice_W32.h @@ -12,7 +12,7 @@ struct IMMDevice; namespace ehs { - class EHS_LIB_IO AudioDevice : public BaseAudioDevice + class EHS_LIB_IO AudioDevice final : public BaseAudioDevice { private: IMMDevice* hdl; diff --git a/include/ehs/io/audio/BaseAudioDevice.h b/include/ehs/io/audio/BaseAudioDevice.h index 92fccd0..a866ac4 100644 --- a/include/ehs/io/audio/BaseAudioDevice.h +++ b/include/ehs/io/audio/BaseAudioDevice.h @@ -10,8 +10,8 @@ namespace ehs { enum class AudioDeviceType { - OUTPUT = 0x0, INPUT = 0x1, + OUTPUT = 0x0, ALL = 0x2 }; @@ -28,13 +28,12 @@ namespace ehs protected: AudioDeviceType type; DataType dataType; - UInt_16 bitDepth; + UInt_16 byteDepth; UInt_32 sampleRate; UInt_32 channels; UInt_32 period; UInt_32 latency; UInt_64 maxFrames; - bool streaming; public: virtual ~BaseAudioDevice() = default; @@ -45,19 +44,15 @@ namespace ehs BaseAudioDevice& operator=(const BaseAudioDevice& device); - virtual void Release(); - virtual void OpenStream(); virtual void CloseStream(); - virtual UInt_64 SendStream(void *data, UInt_64 size); + virtual UInt_64 SendStream(const void *data, UInt_64 size); - virtual UInt_64 GetAvailFrames() const; + virtual UInt_64 ReceiveStream(void *data, UInt_64 size); - virtual Byte* Map(UInt_64* offset, UInt_64* frames); - - virtual void UnMap(UInt_64 offset, UInt_64 frames); + void BridgeStreams(UInt_64 bufferSize); AudioDeviceType GetType() const; @@ -89,7 +84,7 @@ namespace ehs UInt_64 GetMaxFrames() const; - bool IsStreaming() const; + virtual bool IsStreaming() const; virtual bool IsValid() const; diff --git a/src/io/audio/AudioDevice_ALSA.cpp b/src/io/audio/AudioDevice_ALSA.cpp deleted file mode 100644 index eec3f11..0000000 --- a/src/io/audio/AudioDevice_ALSA.cpp +++ /dev/null @@ -1,216 +0,0 @@ -#include "ehs/io/audio/AudioDevice_ALSA.h" -#include "ehs/EHS.h" -#include "ehs/Log.h" -#include "ehs/system/Semaphore.h" - -#include -#include -#include - -#include "ehs/io/audio/AudioDevice.h" - -namespace ehs -{ - Array AudioDevice::devices; - - void AudioDevice::RegistryEventGlobal(void *user_data, UInt_32 id, UInt_32 permissions, const char *type, UInt_32 version, const spa_dict *props) - { - const Str_8 mediaClass = spa_dict_lookup(props, PW_KEY_MEDIA_CLASS); - - if (mediaClass.Size() && (mediaClass == "Audio/Sink" || mediaClass == "Audio/Source")) - { - AudioDevice device; - - if (mediaClass == "Audio/Sink") - device.type = AudioDeviceType::OUTPUT; - else if (mediaClass == "Audio/Source") - device.type = AudioDeviceType::INPUT; - - device.id = id; - device.name = spa_dict_lookup(props, PW_KEY_NODE_NAME); - - EHS_LOG_INT(LogType::INFO, 1, "\nDevice Name: " + device.name + "\nId: " + Str_8::FromNum(device.id)); - - const pw_metadata *metadata = pw_core_get_metadata(); - - devices.Push(device); - } - } - - void AudioDevice::RegistryEventGlobalRemove(void *user_data, UInt_32 id) - { - } - - AudioDevice::~AudioDevice() - { - } - - AudioDevice::AudioDevice() - { - } - - AudioDevice::AudioDevice(AudioDevice&& device) noexcept - : BaseAudioDevice(device) - { - } - - AudioDevice::AudioDevice(const AudioDevice& device) - : BaseAudioDevice(device) - { - } - - AudioDevice& AudioDevice::operator=(AudioDevice&& device) noexcept - { - if (this == &device) - return *this; - - BaseAudioDevice::operator=(device); - - return *this; - } - - AudioDevice& AudioDevice::operator=(const AudioDevice& device) - { - if (this == &device) - return *this; - - BaseAudioDevice::operator=(device); - - return *this; - } - - void AudioDevice::Release() - { - if (!IsValid()) - return; - } - - void AudioDevice::OpenStream() - { - if (streaming) - return; - - pw_init(nullptr, nullptr); - - loop = pw_loop_new(nullptr); - context = pw_context_new(loop, nullptr, 0); - core = pw_context_connect(context, nullptr, 0); - - spa_audio_info_raw info = { - .format = SPA_AUDIO_FORMAT_F32, - .rate = 48000, - .channels = 2, - .position = { - SPA_AUDIO_CHANNEL_FL, - SPA_AUDIO_CHANNEL_FR, - SPA_AUDIO_CHANNEL_FC, - SPA_AUDIO_CHANNEL_LFE, - SPA_AUDIO_CHANNEL_SL, - SPA_AUDIO_CHANNEL_SR, - SPA_AUDIO_CHANNEL_RL, - SPA_AUDIO_CHANNEL_RR - } - }; - - pw_properties *props = pw_properties_new( - PW_KEY_MEDIA_TYPE, "Audio", - PW_KEY_MEDIA_CATEGORY, "Playback", - PW_KEY_MEDIA_ROLE, "Game", - nullptr - ); - - spa_pod_builder b = {}; - Byte buffer[1024]; - - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - - const spa_pod *pod[] = {spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &info)}; - - pw_stream_connect( - stream, - PW_DIRECTION_OUTPUT, - PW_ID_ANY, - (pw_stream_flags)(PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_MAP_BUFFERS), - pod, - 1 - ); - - streaming = true; - } - - void AudioDevice::CloseStream() - { - if (!streaming) - return; - - pw_stream_destroy(stream); - pw_core_disconnect(core); - pw_context_destroy(context); - pw_loop_destroy(loop); - pw_deinit(); - - streaming = false; - } - - UInt_64 AudioDevice::SendStream(void *data, const UInt_64 size) - { - while (pw_loop_iterate(loop, 0)); - - if (pw_stream_get_state(stream, nullptr) != PW_STREAM_STATE_STREAMING) - return 0; - - pw_buffer *buf = pw_stream_dequeue_buffer(stream); - if (!buf) - return 0; - - UInt_64 out = 0; - - spa_data &result = buf->buffer->datas[0]; - - if (size > result.maxsize) - out = result.maxsize; - else - out = size; - - Util::Copy(result.data, data, out); - - pw_stream_queue_buffer(stream, buf); - - return out; - } - - bool AudioDevice::IsValid() const - { - return true; - } - - AudioDevice AudioDevice::GetDefault(const AudioDeviceType type) - { - pw_init(nullptr, nullptr); - - pw_loop *loop = pw_loop_new(nullptr); - pw_context *context = pw_context_new(loop, nullptr, 0); - pw_core *core = pw_context_connect(context, nullptr, 0); - pw_registry *registry = pw_core_get_registry(core, PW_VERSION_REGISTRY, 0); - spa_hook listener = {}; - - constexpr pw_registry_events events = { - .version = PW_VERSION_REGISTRY_EVENTS, - .global = RegistryEventGlobal, - .global_remove = RegistryEventGlobalRemove - }; - - pw_registry_add_listener(registry, &listener, &events, nullptr); - - while (pw_loop_iterate(loop, 10)); - - constexpr pw_metadata_events - - return {}; - } - - Array AudioDevice::Get(const AudioDeviceType type, const AudioDeviceState state) - { - return {}; - } -} diff --git a/src/io/audio/AudioDevice_PW.cpp b/src/io/audio/AudioDevice_PW.cpp new file mode 100644 index 0000000..9e1071e --- /dev/null +++ b/src/io/audio/AudioDevice_PW.cpp @@ -0,0 +1,409 @@ +#include "ehs/io/audio/AudioDevice_PW.h" +#include "ehs/EHS.h" +#include "ehs/Log.h" +#include "ehs/system/Semaphore.h" + +#include +#include +#include +#include + +namespace ehs +{ + Array AudioDevice::devices; + + void AudioDevice::RegistryEventGlobal(void *data, const UInt_32 id, UInt_32 permissions, const char *type, UInt_32 version, const spa_dict *props) + { + if (Str_8::Cmp(type, PW_TYPE_INTERFACE_Node)) + { + const Str_8 mediaClass = spa_dict_lookup(props, PW_KEY_MEDIA_CLASS); + if (mediaClass.Size() && (mediaClass == "Audio/Sink" || mediaClass == "Audio/Source")) + { + AudioDevice device; + + if (mediaClass == "Audio/Sink") + device.type = AudioDeviceType::OUTPUT; + else if (mediaClass == "Audio/Source") + device.type = AudioDeviceType::INPUT; + + device.id = id; + device.name = spa_dict_lookup(props, PW_KEY_NODE_NAME); + + EHS_LOG_INT(LogType::INFO, 1, "\nDevice Name: " + device.name + "\nId: " + Str_8::FromNum(device.id)); + + devices.Push(device); + } + } + } + + void AudioDevice::RegistryEventGlobalRemove(void *data, UInt_32 id) + { + } + + void AudioDevice::OnParamChanged(void *data, UInt_32 id, const spa_pod *param) + { + if (!param) + return; + + if (id == SPA_PARAM_Buffers) + { + AudioDevice *device = (AudioDevice *)data; + + spa_pod_object *obj = (spa_pod_object *)param; + spa_pod_prop *prop; + + SPA_POD_OBJECT_FOREACH(obj, prop) + { + if (prop->key == SPA_PARAM_BUFFERS_size) + { + spa_pod_get_int(&prop->value, (int32_t *)&device->maxFrames); + device->maxFrames = device->maxFrames / device->byteDepth / device->channels; + } + } + } + } + + AudioDevice::~AudioDevice() + { + if (!IsStreaming()) + return; + + if (output) + { + pw_stream_disconnect(output); + pw_stream_destroy(output); + output = nullptr; + } + + if (input) + { + pw_stream_disconnect(input); + pw_stream_destroy(input); + input = nullptr; + } + + pw_core_disconnect(core); + core = nullptr; + + pw_context_destroy(context); + context = nullptr; + + pw_loop_destroy(loop); + loop = nullptr; + } + + AudioDevice::AudioDevice() + : id(0), loop(nullptr), context(nullptr), core(nullptr), input(nullptr), output(nullptr) + { + } + + AudioDevice::AudioDevice(AudioDevice&& device) noexcept + : BaseAudioDevice(device), id(device.id), name((Str_8 &&)device.name), loop(device.loop), + context(device.context), core(device.core), input(device.input), output(device.output) + { + device.id = 0; + device.loop = nullptr; + device.context = nullptr; + device.core = nullptr; + device.input = nullptr; + device.output = nullptr; + } + + AudioDevice::AudioDevice(const AudioDevice& device) + : BaseAudioDevice(device), id(device.id), name(device.name), loop(nullptr), context(nullptr), core(nullptr), + input(nullptr), output(nullptr) + { + } + + AudioDevice& AudioDevice::operator=(AudioDevice&& device) noexcept + { + if (this == &device) + return *this; + + BaseAudioDevice::operator=(device); + + id = device.id; + name = (Str_8 &&)device.name; + loop = device.loop; + context = device.context; + core = device.core; + input = device.input; + output = device.output; + + device.id = 0; + device.loop = nullptr; + device.context = nullptr; + device.core = nullptr; + device.input = nullptr; + device.output = nullptr; + + return *this; + } + + AudioDevice& AudioDevice::operator=(const AudioDevice& device) + { + if (this == &device) + return *this; + + BaseAudioDevice::operator=(device); + + id = device.id; + name = device.name; + loop = nullptr; + context = nullptr; + core = nullptr; + input = nullptr; + output = nullptr; + + return *this; + } + + void AudioDevice::OpenStream() + { + if (!IsValid() || IsStreaming()) + return; + + loop = pw_loop_new(nullptr); + context = pw_context_new(loop, nullptr, 0); + core = pw_context_connect(context, nullptr, 0); + + spa_audio_info_raw info = { + .format = SPA_AUDIO_FORMAT_F32, + .rate = GetSampleRate(), + .channels = GetChannels(), + .position = { + SPA_AUDIO_CHANNEL_FL, + SPA_AUDIO_CHANNEL_FR, + SPA_AUDIO_CHANNEL_FC, + SPA_AUDIO_CHANNEL_LFE, + SPA_AUDIO_CHANNEL_SL, + SPA_AUDIO_CHANNEL_SR, + SPA_AUDIO_CHANNEL_RL, + SPA_AUDIO_CHANNEL_RR + } + }; + + pw_properties *props = pw_properties_new( + PW_KEY_MEDIA_TYPE, "Audio", + PW_KEY_MEDIA_CATEGORY, GetCategory(), + PW_KEY_MEDIA_ROLE, "Game", + nullptr + ); + + spa_pod_builder b = {}; + Byte buffer[1024]; + + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + + const spa_pod *pod[] = {spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &info)}; + + if (GetType() == AudioDeviceType::INPUT || GetType() == AudioDeviceType::ALL) + { + input = pw_stream_new(core, "", props); + if (!input) + { + EHS_LOG_INT(LogType::ERR, 1, "Failed to create input stream for audio device."); + return; + } + + pw_stream_connect( + output, + PW_DIRECTION_INPUT, + id, + (pw_stream_flags)(PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_MAP_BUFFERS), + pod, + 1 + ); + } + + if (GetType() == AudioDeviceType::OUTPUT || GetType() == AudioDeviceType::ALL) + { + output = pw_stream_new(core, "", props); + if (!output) + { + EHS_LOG_INT(LogType::ERR, 1, "Failed to create output stream for audio device."); + return; + } + + pw_stream_connect( + output, + PW_DIRECTION_OUTPUT, + id, + (pw_stream_flags)(PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_MAP_BUFFERS), + pod, + 1 + ); + } + + static constexpr pw_stream_events streamEvents = { + .version = PW_VERSION_STREAM_EVENTS, + .param_changed = OnParamChanged + }; + + spa_hook streamListener = {}; + pw_stream_add_listener(output, &streamListener, &streamEvents, this); + + EHS_LOG_SUCCESS(); + } + + void AudioDevice::CloseStream() + { + if (!IsStreaming()) + return; + + if (output) + { + pw_stream_disconnect(output); + pw_stream_destroy(output); + output = nullptr; + } + + if (input) + { + pw_stream_disconnect(input); + pw_stream_destroy(input); + input = nullptr; + } + + pw_core_disconnect(core); + core = nullptr; + + pw_context_destroy(context); + context = nullptr; + + pw_loop_destroy(loop); + loop = nullptr; + } + + UInt_64 AudioDevice::SendStream(const void *data, const UInt_64 size) + { + if (GetType() != AudioDeviceType::OUTPUT && GetType() != AudioDeviceType::ALL) + { + EHS_LOG_INT(LogType::ERR, 0, "You can only send an audio stream on an output audio device."); + return 0; + } + + pw_loop_iterate(loop, 0); + + if (pw_stream_get_state(output, nullptr) != PW_STREAM_STATE_STREAMING) + return 0; + + pw_buffer *buf = pw_stream_dequeue_buffer(output); + if (!buf) + return 0; + + UInt_64 out = 0; + + spa_data &result = buf->buffer->datas[0]; + + if (size > result.maxsize) + out = result.maxsize; + else + out = size; + + Util::Copy(result.data, data, out); + + pw_stream_queue_buffer(output, buf); + + EHS_LOG_SUCCESS(); + + return out; + } + + UInt_64 AudioDevice::ReceiveStream(void *data, const UInt_64 size) + { + if (GetType() != AudioDeviceType::INPUT && GetType() != AudioDeviceType::ALL) + { + EHS_LOG_INT(LogType::ERR, 0, "You can only send an audio stream on an input audio device."); + return 0; + } + + pw_loop_iterate(loop, 0); + + if (pw_stream_get_state(input, nullptr) != PW_STREAM_STATE_STREAMING) + return 0; + + pw_buffer *buf = pw_stream_dequeue_buffer(input); + if (!buf) + return 0; + + spa_data &result = buf->buffer->datas[0]; + + UInt_64 in; + if (result.chunk->size <= size) + in = result.chunk->size; + else + in = size; + + Util::Copy(data, result.data, in); + + pw_stream_queue_buffer(input, buf); + + EHS_LOG_SUCCESS(); + + return in; + } + + bool AudioDevice::IsStreaming() const + { + return loop && context && core && (input || output); + } + + bool AudioDevice::IsValid() const + { + return id; + } + + AudioDevice AudioDevice::GetDefault(const AudioDeviceType type) + { + pw_init(nullptr, nullptr); + + AudioDevice result; + result.type = type; + result.id = PW_ID_ANY; + + return result; + } + + Array AudioDevice::Get(const AudioDeviceType type, const AudioDeviceState state) + { + pw_init(nullptr, nullptr); + + pw_loop *loop = pw_loop_new(nullptr); + pw_context *context = pw_context_new(loop, nullptr, 0); + pw_core *core = pw_context_connect(context, nullptr, 0); + pw_registry *registry = pw_core_get_registry(core, PW_VERSION_REGISTRY, 0); + spa_hook listener = {}; + + static constexpr pw_registry_events events = { + .version = PW_VERSION_REGISTRY_EVENTS, + .global = RegistryEventGlobal, + .global_remove = RegistryEventGlobalRemove + }; + + pw_registry_add_listener(registry, &listener, &events, registry); + + while (pw_loop_iterate(loop, 10)); + + pw_core_disconnect(core); + pw_context_destroy(context); + pw_loop_destroy(loop); + + return devices; + } + + Str_8 AudioDevice::GetCategory() const + { + switch (GetType()) + { + case AudioDeviceType::INPUT: + return "Capture"; + case AudioDeviceType::OUTPUT: + return "Playback"; + case AudioDeviceType::ALL: + return "Duplex"; + default: + return ""; + } + } +} diff --git a/src/io/audio/BaseAudioDevice.cpp b/src/io/audio/BaseAudioDevice.cpp index c551324..7eb2335 100644 --- a/src/io/audio/BaseAudioDevice.cpp +++ b/src/io/audio/BaseAudioDevice.cpp @@ -3,14 +3,14 @@ namespace ehs { BaseAudioDevice::BaseAudioDevice() - : type(AudioDeviceType::ALL), dataType(DataType::SINT_8), bitDepth(0), sampleRate(0), channels(0), - period(20000), latency(150000), maxFrames(0), streaming(false) + : type(AudioDeviceType::ALL), dataType(DataType::SINT_8), byteDepth(0), sampleRate(0), channels(0), + period(20000), latency(150000), maxFrames(0) { } BaseAudioDevice::BaseAudioDevice(const BaseAudioDevice& device) - : type(device.type), dataType(device.dataType), bitDepth(device.bitDepth), sampleRate(device.sampleRate), - channels(device.channels), period(device.period), latency(device.latency), maxFrames(0), streaming(false) + : type(device.type), dataType(device.dataType), byteDepth(device.byteDepth), sampleRate(device.sampleRate), + channels(device.channels), period(device.period), latency(device.latency), maxFrames(0) { } @@ -21,21 +21,16 @@ namespace ehs type = device.type; dataType = device.dataType; - bitDepth = device.bitDepth; + byteDepth = device.byteDepth; sampleRate = device.sampleRate; channels = device.channels; period = device.period; latency = device.latency; maxFrames = device.maxFrames; - streaming = false; return *this; } - void BaseAudioDevice::Release() - { - } - void BaseAudioDevice::OpenStream() { } @@ -44,37 +39,43 @@ namespace ehs { } - UInt_64 BaseAudioDevice::SendStream(void *data, UInt_64 size) + UInt_64 BaseAudioDevice::SendStream(const void *data, const UInt_64 size) { return 0; } - UInt_64 BaseAudioDevice::GetAvailFrames() const + UInt_64 BaseAudioDevice::ReceiveStream(void *data, const UInt_64 size) { return 0; } - Byte* BaseAudioDevice::Map(UInt_64* offset, UInt_64* frames) + void BaseAudioDevice::BridgeStreams(const UInt_64 bufferSize) { - return nullptr; + Byte* buffer = new Byte[bufferSize]; + + UInt_64 result = ReceiveStream(buffer, bufferSize); + while (result < bufferSize) + result += ReceiveStream(&buffer[result], bufferSize - result); + + result -= SendStream(buffer, result); + while (result) + result -= SendStream(&buffer[bufferSize - result], result); + + delete[] buffer; } - void BaseAudioDevice::UnMap(const UInt_64 offset, const UInt_64 frames) - { - } - - AudioDeviceType BaseAudioDevice::GetType() const + AudioDeviceType BaseAudioDevice::GetType() const { return type; } void BaseAudioDevice::SetDataType(const DataType newDataType) { - if (streaming) + if (IsStreaming()) return; dataType = newDataType; - bitDepth = ToBitDepth(newDataType); + byteDepth = ToByteDepth(newDataType); } DataType BaseAudioDevice::GetDataType() const @@ -84,17 +85,17 @@ namespace ehs UInt_8 BaseAudioDevice::GetByteDepth() const { - return bitDepth / 8; + return byteDepth; } UInt_16 BaseAudioDevice::GetBitDepth() const { - return bitDepth; + return byteDepth * 8; } void BaseAudioDevice::SetSampleRate(const UInt_32 newSampleRate) { - if (streaming) + if (IsStreaming()) return; sampleRate = newSampleRate; @@ -107,7 +108,7 @@ namespace ehs void BaseAudioDevice::SetChannels(const UInt_32 newChannels) { - if (streaming) + if (IsStreaming()) return; channels = newChannels; @@ -120,12 +121,12 @@ namespace ehs UInt_32 BaseAudioDevice::GetFrameSize() const { - return bitDepth / 8 * channels; + return byteDepth * channels; } void BaseAudioDevice::SetPeriod(const UInt_32 newPeriod) { - if (streaming) + if (IsStreaming()) return; period = newPeriod; @@ -138,7 +139,7 @@ namespace ehs void BaseAudioDevice::SetLatency(const UInt_32 newLatency) { - if (streaming) + if (IsStreaming()) return; latency = newLatency; @@ -156,7 +157,7 @@ namespace ehs bool BaseAudioDevice::IsStreaming() const { - return streaming; + return false; } bool BaseAudioDevice::IsValid() const