add peakValues to scripting API

This commit is contained in:
Zach Pomerantz 2017-06-27 17:37:13 -04:00
parent 3f57e5eb4d
commit 5353437f59
2 changed files with 118 additions and 27 deletions

View file

@ -34,28 +34,44 @@ Setting::Handle<QString>& getSetting(bool contextIsHMD, QAudio::Mode mode) {
}
}
QHash<int, QByteArray> AudioDeviceList::_roles {
{ Qt::DisplayRole, "display" },
{ Qt::CheckStateRole, "selected" }
enum AudioDeviceRole {
DisplayRole = Qt::DisplayRole,
CheckStateRole = Qt::CheckStateRole,
PeakRole = Qt::UserRole
};
QHash<int, QByteArray> AudioDeviceList::_roles {
{ DisplayRole, "display" },
{ CheckStateRole, "selected" },
{ PeakRole, "peak" }
};
Qt::ItemFlags AudioDeviceList::_flags { Qt::ItemIsSelectable | Qt::ItemIsEnabled };
QVariant AudioDeviceList::data(const QModelIndex& index, int role) const {
if (!index.isValid() || index.row() >= _devices.size()) {
if (!index.isValid() || index.row() >= rowCount()) {
return QVariant();
}
if (role == Qt::DisplayRole) {
return _devices.at(index.row()).display;
} else if (role == Qt::CheckStateRole) {
return _devices.at(index.row()).selected;
if (role == DisplayRole) {
return _devices.at(index.row())->display;
} else if (role == CheckStateRole) {
return _devices.at(index.row())->selected;
} else {
return QVariant();
}
}
QVariant AudioInputDeviceList::data(const QModelIndex& index, int role) const {
if (index.isValid() && index.row() < rowCount() && role == PeakRole) {
return std::static_pointer_cast<AudioInputDevice>(_devices.at(index.row()))->peak;
} else {
return AudioDeviceList::data(index, role);
}
}
bool AudioDeviceList::setData(const QModelIndex& index, const QVariant& value, int role) {
if (!index.isValid() || index.row() >= _devices.size() || role != Qt::CheckStateRole) {
if (!index.isValid() || index.row() >= rowCount() || role != CheckStateRole) {
return false;
}
@ -73,19 +89,19 @@ bool AudioDeviceList::setDevice(int row, bool fromUser) {
auto& device = _devices[row];
// skip if already selected
if (!device.selected) {
if (!device->selected) {
auto client = DependencyManager::get<AudioClient>();
QMetaObject::invokeMethod(client.data(), "switchAudioDevice", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(bool, success),
Q_ARG(QAudio::Mode, _mode),
Q_ARG(const QAudioDeviceInfo&, device.info));
Q_ARG(const QAudioDeviceInfo&, device->info));
if (success) {
device.selected = true;
device->selected = true;
if (fromUser) {
emit deviceSelected(device.info, _selectedDevice);
emit deviceSelected(device->info, _selectedDevice);
}
emit deviceChanged(device.info);
emit deviceChanged(device->info);
}
}
@ -100,7 +116,7 @@ void AudioDeviceList::resetDevice(bool contextIsHMD, const QString& device) {
if (!device.isNull()) {
auto i = 0;
for (; i < rowCount(); ++i) {
if (device == _devices[i].info.deviceName()) {
if (device == _devices[i]->info.deviceName()) {
break;
}
}
@ -138,8 +154,8 @@ void AudioDeviceList::onDeviceChanged(const QAudioDeviceInfo& device) {
_selectedDevice = device;
QModelIndex index;
for (auto i = 0; i < _devices.size(); ++i) {
AudioDevice& device = _devices[i];
for (auto i = 0; i < rowCount(); ++i) {
AudioDevice& device = *_devices[i];
if (device.selected && device.info != _selectedDevice) {
device.selected = false;
@ -166,17 +182,47 @@ void AudioDeviceList::onDevicesChanged(const QList<QAudioDeviceInfo>& devices) {
.remove("Device")
.replace(" )", ")");
device.selected = (device.info == _selectedDevice);
_devices.push_back(device);
_devices.push_back(newDevice(device));
}
endResetModel();
}
bool AudioInputDeviceList::peakValuesAvailable() {
std::call_once(_peakFlag, [&] {
_peakValuesAvailable = DependencyManager::get<AudioClient>()->peakValuesAvailable();
});
return _peakValuesAvailable;
}
void AudioInputDeviceList::setPeakValuesEnabled(bool enable) {
if (peakValuesAvailable() && (enable != _peakValuesEnabled)) {
DependencyManager::get<AudioClient>()->enablePeakValues(enable);
_peakValuesEnabled = enable;
emit peakValuesEnabledChanged(_peakValuesEnabled);
}
}
void AudioInputDeviceList::onPeakValueListChanged(const QList<float>& peakValueList) {
assert(_mode == QAudio::AudioInput);
if (peakValueList.length() != rowCount()) {
qWarning() << "AudioDeviceList" << __FUNCTION__ << "length mismatch";
}
for (auto i = 0; i < rowCount(); ++i) {
std::static_pointer_cast<AudioInputDevice>(_devices[i])->peak = peakValueList[i];
}
emit dataChanged(createIndex(0, 0), createIndex(rowCount() - 1, 0), { PeakRole });
}
AudioDevices::AudioDevices(bool& contextIsHMD) : _contextIsHMD(contextIsHMD) {
auto client = DependencyManager::get<AudioClient>();
connect(client.data(), &AudioClient::deviceChanged, this, &AudioDevices::onDeviceChanged, Qt::QueuedConnection);
connect(client.data(), &AudioClient::devicesChanged, this, &AudioDevices::onDevicesChanged, Qt::QueuedConnection);
connect(client.data(), &AudioClient::peakValueListChanged, &_inputs, &AudioInputDeviceList::onPeakValueListChanged, Qt::QueuedConnection);
// connections are made after client is initialized, so we must also fetch the devices
_inputs.onDeviceChanged(client->getActiveAudioDevice(QAudio::AudioInput));

View file

@ -12,6 +12,9 @@
#ifndef hifi_scripting_AudioDevices_h
#define hifi_scripting_AudioDevices_h
#include <memory>
#include <mutex>
#include <QObject>
#include <QAbstractListModel>
#include <QAudioDeviceInfo>
@ -29,7 +32,11 @@ class AudioDeviceList : public QAbstractListModel {
Q_OBJECT
public:
AudioDeviceList(QAudio::Mode mode) : _mode(mode) {}
AudioDeviceList(QAudio::Mode mode = QAudio::AudioOutput) : _mode(mode) {}
~AudioDeviceList() = default;
virtual std::shared_ptr<AudioDevice> newDevice(const AudioDevice& device)
{ return std::make_shared<AudioDevice>(device); }
int rowCount(const QModelIndex& parent = QModelIndex()) const override { Q_UNUSED(parent); return _devices.size(); }
QHash<int, QByteArray> roleNames() const override { return _roles; }
@ -47,11 +54,11 @@ signals:
const QAudioDeviceInfo& previousDevice = QAudioDeviceInfo());
void deviceChanged(const QAudioDeviceInfo& device);
private slots:
protected slots:
void onDeviceChanged(const QAudioDeviceInfo& device);
void onDevicesChanged(const QList<QAudioDeviceInfo>& devices);
private:
protected:
friend class AudioDevices;
bool setDevice(int index, bool fromUser);
@ -59,16 +66,54 @@ private:
static QHash<int, QByteArray> _roles;
static Qt::ItemFlags _flags;
QAudio::Mode _mode;
QAudio::Mode _mode { QAudio::AudioOutput };
QAudioDeviceInfo _selectedDevice;
QList<AudioDevice> _devices;
QList<std::shared_ptr<AudioDevice>> _devices;
};
class AudioInputDevice : public AudioDevice {
public:
AudioInputDevice(const AudioDevice& device) : AudioDevice(device) {}
float peak { 0.0f };
};
class AudioInputDeviceList : public AudioDeviceList {
Q_OBJECT
Q_PROPERTY(bool peakValuesAvailable READ peakValuesAvailable)
Q_PROPERTY(bool peakValuesEnabled READ peakValuesEnabled WRITE setPeakValuesEnabled NOTIFY peakValuesEnabledChanged)
public:
AudioInputDeviceList() : AudioDeviceList(QAudio::AudioInput) {}
virtual ~AudioInputDeviceList() = default;
virtual std::shared_ptr<AudioDevice> newDevice(const AudioDevice& device)
{ return std::make_shared<AudioInputDevice>(device); }
QVariant data(const QModelIndex& index, int role) const override;
signals:
void peakValuesEnabledChanged(bool enabled);
protected slots:
void onPeakValueListChanged(const QList<float>& peakValueList);
protected:
friend class AudioDevices;
bool peakValuesAvailable();
std::once_flag _peakFlag;
bool _peakValuesAvailable;
bool peakValuesEnabled() const { return _peakValuesEnabled; }
void setPeakValuesEnabled(bool enable);
bool _peakValuesEnabled { false };
};
class Audio;
class AudioDevices : public QObject {
Q_OBJECT
Q_PROPERTY(AudioDeviceList* input READ getInputList NOTIFY nop)
Q_PROPERTY(AudioInputDeviceList* input READ getInputList NOTIFY nop)
Q_PROPERTY(AudioDeviceList* output READ getOutputList NOTIFY nop)
public:
@ -86,11 +131,11 @@ private slots:
private:
friend class Audio;
AudioDeviceList* getInputList() { return &_inputs; }
AudioInputDeviceList* getInputList() { return &_inputs; }
AudioDeviceList* getOutputList() { return &_outputs; }
AudioDeviceList _inputs { QAudio::AudioInput };
AudioDeviceList _outputs { QAudio::AudioOutput };
AudioInputDeviceList _inputs;
AudioDeviceList _outputs;
bool& _contextIsHMD;
};