Fixed Mat and CMakeLists

This commit is contained in:
Arron David Nelson 2024-09-16 16:18:49 -07:00
parent 25762b0c29
commit 681c0d09be
8 changed files with 620 additions and 424 deletions

View File

@ -208,7 +208,7 @@ elseif (IS_OS_LINUX)
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/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

View File

@ -5,5 +5,5 @@
#if defined(EHS_OS_WINDOWS)
#include "AudioDevice_W32.h"
#elif defined(EHS_OS_LINUX)
#include "AudioDevice_ALSA.h"
#include "AudioDevice_PW.h"
#endif

View File

@ -3,16 +3,15 @@
#include "ehs/EHS.h"
#include "BaseAudioDevice.h"
#include <spa/param/audio/format-utils.h>
#include <pipewire/pipewire.h>
#include <pipewire/loop.h>
#include <pipewire/context.h>
#include <pipewire/stream.h>
#include <pipewire/keys.h>
#include <spa/param/audio/format-utils.h>
namespace ehs
{
class EHS_LIB_IO AudioDevice : public BaseAudioDevice
class EHS_LIB_IO AudioDevice final : public BaseAudioDevice
{
private:
static Array<AudioDevice> 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<AudioDevice> Get(AudioDeviceType type, AudioDeviceState state);
private:
Str_8 GetCategory() const;
};
}

View File

@ -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;

View File

@ -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;

View File

@ -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 <spa/utils/list.h>
#include <spa/utils/result.h>
#include <spa/utils/dict.h>
#include "ehs/io/audio/AudioDevice.h"
namespace ehs
{
Array<AudioDevice> 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> AudioDevice::Get(const AudioDeviceType type, const AudioDeviceState state)
{
return {};
}
}

View File

@ -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 <spa/utils/result.h>
#include <spa/utils/dict.h>
#include <spa/buffer/buffer.h>
#include <spa/param/latency-utils.h>
namespace ehs
{
Array<AudioDevice> 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> 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 "";
}
}
}

View File

@ -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,23 +39,29 @@ 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];
void BaseAudioDevice::UnMap(const UInt_64 offset, const UInt_64 frames)
{
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;
}
AudioDeviceType BaseAudioDevice::GetType() const
@ -70,11 +71,11 @@ namespace ehs
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