Compare commits

..

6 Commits

Author SHA1 Message Date
WarmUpTill
70dad8ebb4 Handle MIDI device disconnect and reconnect 2024-03-09 12:00:52 +01:00
WarmUpTill
497b3b3e04 Clean up macro import and add action queues 2024-03-09 12:00:52 +01:00
WarmUpTill
891811aa47 Convert audio volume thresholds to new format 2024-03-09 09:18:29 +01:00
WarmUpTill
be9ddaa4c9 Increase precision of percent based volume threshold input 2024-03-09 09:18:29 +01:00
WarmUpTill
03494c2915 Adapt to volume widget slider changes 2024-03-09 09:18:29 +01:00
WarmUpTill
bcf7c247bf Increase precision of volume widget slider 2024-03-09 09:18:29 +01:00
16 changed files with 336 additions and 86 deletions

View File

@@ -151,6 +151,8 @@ target_sources(
lib/utils/backup.hpp
lib/utils/curl-helper.cpp
lib/utils/curl-helper.hpp
lib/utils/double-slider.cpp
lib/utils/double-slider.hpp
lib/utils/duration-control.cpp
lib/utils/duration-control.hpp
lib/utils/duration.cpp

View File

@@ -437,10 +437,8 @@ AudioSwitchWidget::AudioSwitchWidget(QWidget *parent, AudioSwitch *s)
audioVolumeThreshold->setMaximum(100);
audioVolumeThreshold->setMinimum(0);
QWidget::connect(volMeter->GetSlider(), SIGNAL(valueChanged(int)),
audioVolumeThreshold, SLOT(setValue(int)));
QWidget::connect(audioVolumeThreshold, SIGNAL(valueChanged(int)),
volMeter->GetSlider(), SLOT(setValue(int)));
QWidget::connect(volMeter->GetSlider(), &DoubleSlider::DoubleValChanged,
[=](double) { SyncSliderAndValueSelection(true); });
QWidget::connect(audioVolumeThreshold, SIGNAL(valueChanged(int)), this,
SLOT(VolumeThresholdChanged(int)));
QWidget::connect(condition, SIGNAL(currentIndexChanged(int)), this,
@@ -487,6 +485,7 @@ AudioSwitchWidget::AudioSwitchWidget(QWidget *parent, AudioSwitch *s)
switchData = s;
loading = false;
SyncSliderAndValueSelection(false);
}
AudioSwitch *AudioSwitchWidget::getSwitchData()
@@ -509,6 +508,21 @@ void AudioSwitchWidget::swapSwitchData(AudioSwitchWidget *s1,
s2->setSwitchData(t);
}
void AudioSwitchWidget::SyncSliderAndValueSelection(bool sliderMoved)
{
if (loading || !switchData) {
return;
}
if (sliderMoved) {
auto sliderPosition = volMeter->GetSlider()->DoubleValue();
audioVolumeThreshold->setValue(sliderPosition);
} else {
volMeter->GetSlider()->SetDoubleVal(
switchData->volumeThreshold);
}
}
void AudioSwitchWidget::UpdateVolmeterSource()
{
delete volMeter;
@@ -520,10 +534,8 @@ void AudioSwitchWidget::UpdateVolmeterSource()
QLayout *layout = this->layout();
layout->addWidget(volMeter);
QWidget::connect(volMeter->GetSlider(), SIGNAL(valueChanged(int)),
audioVolumeThreshold, SLOT(setValue(int)));
QWidget::connect(audioVolumeThreshold, SIGNAL(valueChanged(int)),
volMeter->GetSlider(), SLOT(setValue(int)));
QWidget::connect(volMeter->GetSlider(), &DoubleSlider::DoubleValChanged,
[=](double) { SyncSliderAndValueSelection(true); });
// Slider will default to 0 so set it manually once
volMeter->GetSlider()->setValue(switchData->volumeThreshold);
@@ -547,8 +559,11 @@ void AudioSwitchWidget::VolumeThresholdChanged(int vol)
return;
}
std::lock_guard<std::mutex> lock(switcher->m);
switchData->volumeThreshold = vol;
{
std::lock_guard<std::mutex> lock(switcher->m);
switchData->volumeThreshold = vol;
}
SyncSliderAndValueSelection(false);
}
void AudioSwitchWidget::ConditionChanged(int cond)

View File

@@ -79,6 +79,7 @@ private slots:
void ConditionChanged(int cond);
void DurationChanged(const Duration &);
void IgnoreInactiveChanged(int state);
void SyncSliderAndValueSelection(bool sliderMoved);
private:
QComboBox *audioSources;

View File

@@ -1,4 +1,5 @@
#include "advanced-scene-switcher.hpp"
#include "action-queue.hpp"
#include "macro-action-edit.hpp"
#include "macro-condition-edit.hpp"
#include "macro-export-import-dialog.hpp"
@@ -248,6 +249,7 @@ void AdvSceneSwitcher::ExportMacros()
}
obs_data_set_array(data, "macros", macroArray);
SaveVariables(data);
SaveActionQueues(data);
obs_data_set_string(data, "version", g_GIT_TAG);
auto json = obs_data_get_json(data);
QString exportString(json);
@@ -370,26 +372,6 @@ bool AdvSceneSwitcher::ResolveMacroImportNameConflict(
return true;
}
static bool variableWithNameExists(const std::string &name)
{
return !!GetVariableByName(name);
}
static void importVariables(obs_data_t *obj)
{
OBSDataArrayAutoRelease array = obs_data_get_array(obj, "variables");
size_t count = obs_data_array_count(array);
for (size_t i = 0; i < count; i++) {
OBSDataAutoRelease data = obs_data_array_item(array, i);
auto var = Variable::Create();
var->Load(data);
if (variableWithNameExists(var->Name())) {
continue;
}
GetVariables().emplace_back(var);
}
}
void AdvSceneSwitcher::ImportMacros()
{
QString json;
@@ -404,7 +386,8 @@ void AdvSceneSwitcher::ImportMacros()
ImportMacros();
return;
}
importVariables(data);
ImportVariables(data);
ImportQueues(data);
auto version = obs_data_get_string(data, "version");
if (strcmp(version, g_GIT_TAG) != 0) {
@@ -425,6 +408,7 @@ void AdvSceneSwitcher::ImportMacros()
OBSDataAutoRelease array_obj = obs_data_array_item(array, i);
auto macro = std::make_shared<Macro>();
macro->Load(array_obj);
RunPostLoadSteps();
if (macroNameExists(macro->Name()) &&
!ResolveMacroImportNameConflict(macro)) {

View File

@@ -358,6 +358,27 @@ void LoadActionQueues(obs_data_t *obj)
}
}
static bool queueWithNameExists(const std::string &name)
{
return !GetWeakActionQueueByName(name).expired();
}
void ImportQueues(obs_data_t *data)
{
OBSDataArrayAutoRelease array =
obs_data_get_array(data, "actionQueues");
size_t count = obs_data_array_count(array);
for (size_t i = 0; i < count; i++) {
OBSDataAutoRelease arrayElement = obs_data_array_item(array, i);
auto queue = ActionQueue::Create();
queue->Load(arrayElement);
if (queueWithNameExists(queue->Name())) {
continue;
}
queues.emplace_back(queue);
}
}
std::weak_ptr<ActionQueue> GetWeakActionQueueByName(const std::string &name)
{
for (const auto &queue : queues) {

View File

@@ -98,6 +98,7 @@ signals:
void SetupActionQueues();
void SaveActionQueues(obs_data_t *);
void LoadActionQueues(obs_data_t *);
void ImportQueues(obs_data_t *);
std::weak_ptr<ActionQueue> GetWeakActionQueueByName(const std::string &name);
std::weak_ptr<ActionQueue> GetWeakActionQueueByQString(const QString &name);
std::string GetActionQueueName(const std::weak_ptr<ActionQueue> &);

View File

@@ -0,0 +1,63 @@
#include "double-slider.hpp"
#include <QWheelEvent>
#include <cmath>
namespace advss {
SliderIgnoreScroll::SliderIgnoreScroll(QWidget *parent) : QSlider(parent)
{
setFocusPolicy(Qt::StrongFocus);
}
SliderIgnoreScroll::SliderIgnoreScroll(Qt::Orientation orientation,
QWidget *parent)
: QSlider(parent)
{
setFocusPolicy(Qt::StrongFocus);
setOrientation(orientation);
}
void SliderIgnoreScroll::wheelEvent(QWheelEvent *event)
{
if (!hasFocus()) {
event->ignore();
} else {
QSlider::wheelEvent(event);
}
}
DoubleSlider::DoubleSlider(QWidget *parent) : SliderIgnoreScroll(parent)
{
connect(this, &DoubleSlider::valueChanged, [this](int val) {
emit DoubleValChanged((minVal / minStep + val) * minStep);
});
}
void DoubleSlider::SetDoubleConstraints(double newMin, double newMax,
double newStep, double val)
{
minVal = newMin;
maxVal = newMax;
minStep = newStep;
double total = maxVal - minVal;
int intMax = int(total / minStep);
setMinimum(0);
setMaximum(intMax);
setSingleStep(1);
SetDoubleVal(val);
}
double DoubleSlider::DoubleValue()
{
return (minVal / minStep + value()) * minStep;
}
void DoubleSlider::SetDoubleVal(double val)
{
setValue(lround((val - minVal) / minStep));
}
} // namespace advss

View File

@@ -0,0 +1,40 @@
// Based on OBS DoubleSlider and SliderIgnoreScroll implementation
#pragma once
#include "export-symbol-helper.hpp"
#include <QSlider>
namespace advss {
class SliderIgnoreScroll : public QSlider {
Q_OBJECT
public:
SliderIgnoreScroll(QWidget *parent = nullptr);
SliderIgnoreScroll(Qt::Orientation orientation,
QWidget *parent = nullptr);
protected:
virtual void wheelEvent(QWheelEvent *event) override;
};
class ADVSS_EXPORT DoubleSlider : public SliderIgnoreScroll {
Q_OBJECT
double minVal = 0, maxVal = 100, minStep = 1;
public:
DoubleSlider(QWidget *parent = nullptr);
void SetDoubleConstraints(double newMin, double newMax, double newStep,
double val);
double DoubleValue();
signals:
void DoubleValChanged(double val);
public slots:
void SetDoubleVal(double val);
};
} // namespace advss

View File

@@ -90,15 +90,17 @@ void VolControl::setPeakMeterType(enum obs_peak_meter_type peakMeterType)
}
VolumeSlider::VolumeSlider(obs_fader_t *fader, QWidget *parent)
: QSlider(parent)
: DoubleSlider(parent)
{
fad = fader;
}
VolumeSlider::VolumeSlider(obs_fader_t *fader, Qt::Orientation orientation,
QWidget *parent)
: QSlider(orientation, parent)
: DoubleSlider(parent)
{
SetDoubleConstraints(0, 100, 0.01, 0);
setOrientation(orientation);
fad = fader;
}
@@ -219,7 +221,6 @@ VolControl::VolControl(OBSSource source_, bool showConfig, bool vertical)
nameLabel->setText(sourceName);
slider->setMinimum(0);
slider->setMaximum(int(FADER_PRECISION));
obs_fader_add_callback(obs_fader, OBSVolumeChanged, this);
obs_volmeter_add_callback(obs_volmeter, OBSVolumeLevel, this);
@@ -592,7 +593,9 @@ void VolumeMeter::mousePressEvent(QMouseEvent *event)
VolumeMeter::VolumeMeter(QWidget *parent, obs_volmeter_t *obs_volmeter,
bool vertical)
: QWidget(parent), obs_volmeter(obs_volmeter), vertical(vertical)
: QWidget(parent),
obs_volmeter(obs_volmeter),
vertical(vertical)
{
setAttribute(Qt::WA_OpaquePaintEvent, true);

View File

@@ -1,4 +1,5 @@
#pragma once
#include "double-slider.hpp"
#include <obs.hpp>
#include <QWidget>
@@ -284,7 +285,7 @@ private:
QLabel *nameLabel;
QLabel *volLabel;
VolumeMeter *volMeter;
QSlider *slider;
DoubleSlider *slider;
QPushButton *config = nullptr;
float levelTotal;
float levelCount;
@@ -327,10 +328,10 @@ public:
inline void SetContextMenu(QMenu *cm) { contextMenu = cm; }
void refreshColors();
QSlider *GetSlider() const { return slider; }
DoubleSlider *GetSlider() const { return slider; }
};
class VolumeSlider : public QSlider {
class VolumeSlider : public DoubleSlider {
Q_OBJECT
public:

View File

@@ -187,6 +187,28 @@ void LoadVariables(obs_data_t *obj)
obs_data_array_release(variablesArray);
}
static bool variableWithNameExists(const std::string &name)
{
return !!GetVariableByName(name);
}
void ImportVariables(obs_data_t *data)
{
obs_data_array_t *array = obs_data_get_array(data, "variables");
size_t count = obs_data_array_count(array);
for (size_t i = 0; i < count; i++) {
obs_data_t *arrayElement = obs_data_array_item(array, i);
auto var = Variable::Create();
var->Load(arrayElement);
obs_data_release(arrayElement);
if (variableWithNameExists(var->Name())) {
continue;
}
GetVariables().emplace_back(var);
}
obs_data_array_release(array);
}
static void populateSaveActionSelection(QComboBox *list)
{
list->addItem(

View File

@@ -88,6 +88,7 @@ signals:
void SaveVariables(obs_data_t *obj);
void LoadVariables(obs_data_t *obj);
void ImportVariables(obs_data_t *obj);
std::deque<std::shared_ptr<Item>> &GetVariables();

View File

@@ -253,7 +253,7 @@ bool MacroConditionAudio::Save(obs_data_t *obj) const
static_cast<int>(_volumeCondition));
obs_data_set_bool(obj, "useDb", _useDb);
_volumeDB.Save(obj, "volumeDB");
obs_data_set_int(obj, "version", 2);
obs_data_set_int(obj, "version", 3);
return true;
}
@@ -294,9 +294,19 @@ bool MacroConditionAudio::Load(obs_data_t *obj)
_volumeCondition = static_cast<VolumeCondition>(
obs_data_get_int(obj, "volumeCondition"));
_volmeter = AddVolmeterToSource(this, _audioSource.GetSource());
if (obs_data_get_int(obj, "version") != 2) {
if (obs_data_get_int(obj, "version") < 2) {
// Set default values for dB handling
_useDb = false;
_volumeDB = 0.0;
// In previous versions the scaling happened in CheckCondition()
// so these values must now be converted to enable compatibility
// with the decibel value based checks.
OBSDataAutoRelease data = obs_data_get_obj(obj, "volume");
auto oldFixedValue = obs_data_get_int(data, "value");
_volumeDB = ((double)oldFixedValue / 1.7) - 60;
_volumePercent = DecibelToPercent(_volumeDB) * 100;
} else {
_useDb = obs_data_get_bool(obj, "useDb");
_volumeDB.Load(obj, "volumeDB");
@@ -416,7 +426,7 @@ MacroConditionAudioEdit::MacroConditionAudioEdit(
_checkTypes(new QComboBox()),
_sources(new SourceSelectionWidget(this, QStringList(), true)),
_condition(new QComboBox()),
_volumePercent(new VariableSpinBox()),
_volumePercent(new VariableDoubleSpinBox()),
_volumeDB(new VariableDoubleSpinBox),
_percentDBToggle(new QPushButton),
_syncOffset(new VariableSpinBox()),
@@ -444,8 +454,9 @@ MacroConditionAudioEdit::MacroConditionAudioEdit(
SLOT(CheckTypeChanged(int)));
QWidget::connect(
_volumePercent,
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
this, SLOT(VolumePercentChanged(const NumberVariable<int> &)));
SIGNAL(NumberVariableChanged(const NumberVariable<double> &)),
this,
SLOT(VolumePercentChanged(const NumberVariable<double> &)));
QWidget::connect(
_syncOffset,
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
@@ -506,11 +517,12 @@ void MacroConditionAudioEdit::UpdateVolmeterSource()
auto layout = this->layout();
layout->addWidget(_volMeter);
QWidget::connect(_volMeter->GetSlider(), &QSlider::valueChanged,
[=](int) { SyncSliderAndValueSelection(true); });
QWidget::connect(_volMeter->GetSlider(),
&DoubleSlider::DoubleValChanged,
[=](double) { SyncSliderAndValueSelection(true); });
// Slider will default to 0 so set it manually once
_volMeter->GetSlider()->setValue(_entryData->_volumePercent);
SyncSliderAndValueSelection(false);
}
void MacroConditionAudioEdit::SourceChanged(const SourceSelection &source)
@@ -531,7 +543,7 @@ void MacroConditionAudioEdit::SourceChanged(const SourceSelection &source)
}
void MacroConditionAudioEdit::VolumePercentChanged(
const NumberVariable<int> &vol)
const NumberVariable<double> &vol)
{
if (_loading || !_entryData) {
return;
@@ -600,35 +612,35 @@ void MacroConditionAudioEdit::PercentDBClicked()
void MacroConditionAudioEdit::SyncSliderAndValueSelection(bool sliderMoved)
{
if (_loading || !_entryData) {
if (!_entryData) {
return;
}
if (sliderMoved) {
auto sliderPosition = _volMeter->GetSlider()->DoubleValue();
// Adjust to the dB scale on the volume meter widget
auto dBScaleValue = ((sliderPosition * 3.0) / 5.0) - 60.0;
if (_entryData->_useDb) {
_volumeDB->SetFixedValue(PercentToDecibel(
(float)_volMeter->GetSlider()->value() /
100.0));
_volumeDB->SetFixedValue(dBScaleValue);
const QSignalBlocker blocker(this);
_volumePercent->SetFixedValue(
_volMeter->GetSlider()->value());
DecibelToPercent(dBScaleValue) * 100);
} else {
_volumePercent->SetFixedValue(
_volMeter->GetSlider()->value());
DecibelToPercent(dBScaleValue) * 100);
const QSignalBlocker blocker(this);
_volumeDB->SetFixedValue(PercentToDecibel(
(float)_volMeter->GetSlider()->value() /
100.0));
_volumeDB->SetFixedValue(dBScaleValue);
}
} else {
const QSignalBlocker blocker(this);
if (_entryData->_useDb) {
_volMeter->GetSlider()->setValue(
DecibelToPercent(_entryData->_volumeDB) * 100);
} else {
_volMeter->GetSlider()->setValue(
_entryData->_volumePercent);
}
double dBValue =
_entryData->_useDb
? _entryData->_volumeDB.GetFixedValue()
: PercentToDecibel(_entryData->_volumePercent /
100.0);
auto sliderPosition = (dBValue + 60.0) * 5 / 3.0;
_volMeter->GetSlider()->SetDoubleVal(sliderPosition);
}
}

View File

@@ -55,11 +55,11 @@ public:
SourceSelection _audioSource;
bool _useDb = false;
NumberVariable<int> _volumePercent = 0;
NumberVariable<double> _volumeDB = 0.0;
NumberVariable<int> _syncOffset = 0;
DoubleVariable _volumePercent = 0;
DoubleVariable _volumeDB = 0.0;
IntVariable _syncOffset = 0;
obs_monitoring_type _monitorType = OBS_MONITORING_TYPE_NONE;
NumberVariable<double> _balance = 0.5;
DoubleVariable _balance = 0.5;
OutputCondition _outputCondition = OutputCondition::ABOVE;
VolumeCondition _volumeCondition = VolumeCondition::ABOVE;
obs_volmeter_t *_volmeter = nullptr;
@@ -97,7 +97,7 @@ public:
private slots:
void SourceChanged(const SourceSelection &);
void VolumePercentChanged(const NumberVariable<int> &vol);
void VolumePercentChanged(const NumberVariable<double> &vol);
void ConditionChanged(int cond);
void CheckTypeChanged(int cond);
void SyncOffsetChanged(const NumberVariable<int> &value);
@@ -117,7 +117,7 @@ private:
QComboBox *_checkTypes;
SourceSelectionWidget *_sources;
QComboBox *_condition;
VariableSpinBox *_volumePercent;
VariableDoubleSpinBox *_volumePercent;
VariableDoubleSpinBox *_volumeDB;
QPushButton *_percentDBToggle;
VariableSpinBox *_syncOffset;

View File

@@ -17,6 +17,55 @@ namespace advss {
std::map<std::pair<MidiDeviceType, std::string>, MidiDeviceInstance *>
MidiDeviceInstance::devices = {};
static bool setupDeviceObservers()
{
static std::vector<libremidi::observer> observers;
for (auto api : libremidi::available_apis()) {
libremidi::observer_configuration cbs;
cbs.input_added = [=](const libremidi::input_port &p) {
auto dev = MidiDeviceInstance::GetDevice(p);
if (!dev) {
return;
}
blog(LOG_INFO, "MIDI input connected: %s",
p.port_name.c_str());
dev->ClosePort();
dev->OpenPort();
};
cbs.input_removed = [=](const libremidi::input_port &p) {
auto dev = MidiDeviceInstance::GetDevice(p);
if (!dev) {
return;
}
blog(LOG_INFO, "MIDI input removed: %s",
p.port_name.c_str());
};
cbs.output_added = [=](const libremidi::output_port &p) {
auto dev = MidiDeviceInstance::GetDevice(p);
if (!dev) {
return;
}
blog(LOG_INFO, "MIDI output connected: %s",
p.port_name.c_str());
dev->ClosePort();
dev->OpenPort();
};
cbs.output_removed = [=](const libremidi::output_port &p) {
auto dev = MidiDeviceInstance::GetDevice(p);
if (!dev) {
return;
}
blog(LOG_INFO, "MIDI output removed: %s",
p.port_name.c_str());
};
observers.emplace_back(
cbs, libremidi::observer_configuration_for(api));
}
return true;
}
static bool deviceObserversAreSetup = setupDeviceObservers();
void MidiDeviceInstance::ResetAllDevices()
{
for (auto const &[_, device] : MidiDeviceInstance::devices) {
@@ -212,8 +261,9 @@ bool MidiMessage::Matches(const MidiMessage &m) const
return channelMatch && noteMatch && valueMatch && typeMatch;
}
MidiDeviceInstance *MidiDeviceInstance::GetDevice(MidiDeviceType type,
const std::string &name)
MidiDeviceInstance *
MidiDeviceInstance::GetDeviceAndOpen(MidiDeviceType type,
const std::string &name)
{
if (name.empty()) {
return nullptr;
@@ -252,6 +302,30 @@ getNameFromPortInformation(const libremidi::port_information &info)
return "[" + name;
}
MidiDeviceInstance *
advss::MidiDeviceInstance::GetDevice(const libremidi::input_port &p)
{
auto key = std::make_pair(MidiDeviceType::INPUT,
getNameFromPortInformation(p));
auto it = MidiDeviceInstance::devices.find(key);
if (it == devices.end()) {
return nullptr;
}
return it->second;
}
MidiDeviceInstance *
advss::MidiDeviceInstance::GetDevice(const libremidi::output_port &p)
{
auto key = std::make_pair(MidiDeviceType::OUTPUT,
getNameFromPortInformation(p));
auto it = MidiDeviceInstance::devices.find(key);
if (it == devices.end()) {
return nullptr;
}
return it->second;
}
static inline QStringList getInputDeviceNames()
{
QStringList devices;
@@ -305,10 +379,11 @@ static std::string getPortNameFromNumber(MidiDeviceType type, int port)
return devices.at(port).toStdString();
}
MidiDeviceInstance *MidiDeviceInstance::GetDevice(MidiDeviceType type, int port)
MidiDeviceInstance *MidiDeviceInstance::GetDeviceAndOpen(MidiDeviceType type,
int port)
{
std::string name = getPortNameFromNumber(type, port);
return GetDevice(type, name);
return GetDeviceAndOpen(type, name);
}
void MidiDevice::Save(obs_data_t *obj) const
@@ -327,13 +402,13 @@ void MidiDevice::Load(obs_data_t *obj)
// TODO: Remove this fallback at some point
if (obs_data_has_user_value(data, "port")) {
auto port = obs_data_get_int(data, "port");
_dev = MidiDeviceInstance::GetDevice(_type, port);
_dev = MidiDeviceInstance::GetDeviceAndOpen(_type, port);
if (_dev) {
_name = _dev->_name;
}
} else {
_name = obs_data_get_string(data, "portName");
_dev = MidiDeviceInstance::GetDevice(_type, _name);
_dev = MidiDeviceInstance::GetDeviceAndOpen(_type, _name);
}
}
@@ -372,8 +447,7 @@ getInPortFromName(const std::string &name)
bool MidiDeviceInstance::OpenPort()
{
if ((_type == MidiDeviceType::INPUT && _in.is_port_open()) ||
(_type == MidiDeviceType::OUTPUT && _out.is_port_open())) {
if (IsOpened()) {
return true;
}
@@ -437,10 +511,15 @@ bool MidiDeviceInstance::OpenPort()
return false;
}
bool MidiDeviceInstance::IsOpened() const
{
return (_type == MidiDeviceType::INPUT && _in.is_port_open()) ||
(_type == MidiDeviceType::OUTPUT && _out.is_port_open());
}
void MidiDeviceInstance::ClosePort()
{
if ((_type == MidiDeviceType::INPUT && !_in.is_port_open()) ||
(_type == MidiDeviceType::OUTPUT && !_out.is_port_open())) {
if (!IsOpened()) {
return;
}
@@ -542,7 +621,6 @@ MidiMessageBuffer MidiDeviceInstance::RegisterForMidiMessages()
void MidiDeviceInstance::ReceiveMidiMessage(libremidi::message &&msg)
{
auto lock = LockContext();
_dispatcher.DispatchMessage(msg);
vblog(LOG_INFO, "received midi: %s",
MidiMessage::ToString(msg).c_str());
@@ -590,7 +668,7 @@ void MidiDeviceSelection::IdxChangedHelper(int idx)
}
auto name = currentText().toStdString();
auto devInstance = MidiDeviceInstance::GetDevice(_type, name);
auto devInstance = MidiDeviceInstance::GetDeviceAndOpen(_type, name);
if (!devInstance) {
DisplayMessage(obs_module_text(
"AdvSceneSwitcher.midi.deviceOpenFail"));

View File

@@ -64,16 +64,22 @@ enum class MidiDeviceType {
class MidiDeviceInstance {
public:
static MidiDeviceInstance *GetDevice(MidiDeviceType type,
const std::string &);
static MidiDeviceInstance *GetDevice(MidiDeviceType type, int port);
static MidiDeviceInstance *GetDeviceAndOpen(MidiDeviceType type,
const std::string &);
static MidiDeviceInstance *GetDeviceAndOpen(MidiDeviceType type,
int port);
static MidiDeviceInstance *GetDevice(const libremidi::input_port &p);
static MidiDeviceInstance *GetDevice(const libremidi::output_port &p);
static void ResetAllDevices();
bool OpenPort();
void ClosePort();
private:
MidiDeviceInstance() = default;
~MidiDeviceInstance() = default;
bool OpenPort();
void ClosePort();
bool IsOpened() const;
bool SendMessge(const MidiMessage &);
[[nodiscard]] MidiMessageBuffer RegisterForMidiMessages();
void ReceiveMidiMessage(libremidi::message &&);