ui(new Ui::ConditionEffectSettings)
{
ui->setupUi(this);
+
+ ui->cbox_axis->setItemData(0, static_cast<std::underlying_type<FFBConditionEffectParameters::Axis>::type>(FFBConditionEffectParameters::Axis::X));
+ ui->cbox_axis->setItemData(1, static_cast<std::underlying_type<FFBConditionEffectParameters::Axis>::type>(FFBConditionEffectParameters::Axis::Y));
connect(ui->cbox_axis, SIGNAL(currentIndexChanged(int)), this, SLOT(axisChanged(const int)));
axisChanged(ui->cbox_axis->currentIndex());
}
qDebug() << "Axis changed" << idx;
}
-void ConditionEffectSettings::fillAvailableSubtypesList(const QStringList& list)
+QString ConditionEffectSettings::conditionSubtypeToConditionName(const ConditionSubtypes subtype) const
+{
+ switch (subtype) {
+ case ConditionSubtypes::DAMPER:
+ return "Damper";
+ case ConditionSubtypes::FRICTION:
+ return "Friction";
+ case ConditionSubtypes::INERTIA:
+ return "Inertia";
+ case ConditionSubtypes::SPRING:
+ return "Spring";
+ default:
+ return "Unknown subtype";
+ }
+}
+
+void ConditionEffectSettings::fillAvailableSubtypesList(const std::vector<ConditionSubtypes>& list)
{
ui->cbox_subtype->clear();
- ui->cbox_subtype->addItems(list);
+ for (const ConditionSubtypes subtype : list)
+ ui->cbox_subtype->addItem(conditionSubtypeToConditionName(subtype), static_cast<std::underlying_type<ConditionSubtypes>::type>(subtype));
}
bool ConditionEffectSettings::fillFromParameters(const std::shared_ptr<FFBEffectParameters> params)
FFBConditionEffectParameters::Axis ConditionEffectSettings::axis() const
{
- switch (ui->cbox_axis->currentIndex()) {
- case 0:
- return FFBConditionEffectParameters::Axis::X;
- case 1:
- return FFBConditionEffectParameters::Axis::Y;
- default:
- return FFBConditionEffectParameters::Axis::NONE;
- }
+ FFBConditionEffectParameters::Axis a = *static_cast<FFBConditionEffectParameters::Axis*>(ui->cbox_axis->currentData(Qt::UserRole).data());
+ return a;
}
QString ConditionEffectSettings::centerX() const
return ui->qle_rightSatY->text();
}
-int ConditionEffectSettings::subtypeIdx() const
+ConditionSubtypes ConditionEffectSettings::subtype() const
{
- return ui->cbox_subtype->currentIndex();
+ ConditionSubtypes subtype = *static_cast<ConditionSubtypes*>(ui->cbox_subtype->currentData(Qt::UserRole).data());
+ return subtype;
}
ConditionEffectSettings::~ConditionEffectSettings()
public:
explicit ConditionEffectSettings(QWidget* parent = nullptr);
~ConditionEffectSettings();
- void fillAvailableSubtypesList(const QStringList& list);
+ QString conditionSubtypeToConditionName(const ConditionSubtypes subtype) const;
+ void fillAvailableSubtypesList(const std::vector<ConditionSubtypes>& list);
bool fillFromParameters(const std::shared_ptr<FFBEffectParameters> params);
bool fillFromParameters(const std::shared_ptr<FFBConditionEffectParameters> cdParams);
FFBConditionEffectParameters::Axis axis() const;
QString leftSatY() const;
QString rightSatX() const;
QString rightSatY() const;
- int subtypeIdx() const;
+ ConditionSubtypes subtype() const;
private:
Ui::ConditionEffectSettings* ui;
m_effects.push_back(FFBEffectFactory::createEffect(FFBEffectTypes::NONE));
}
-QStringList FFBDevice::availableConditionSubtypesList() const
+const std::vector<ConditionSubtypes>& FFBDevice::availableConditionSubtypesList() const
{
- QStringList list;
-
- for (const ConditionSubtypes s : m_availableConditionSubtypes)
- list << conditionSubtypeName(s);
-
- return list;
+ return m_availableConditionSubtypes;
}
-QStringList FFBDevice::availableEffectsList() const
+const std::vector<FFBEffectTypes>& FFBDevice::availableEffectsList() const
{
- QStringList list;
-
- for (const FFBEffectTypes e : m_availableEffects)
- list << effectName(e);
-
- return list;
+ return m_availableEffects;
}
-QStringList FFBDevice::availableWaveformsList() const
+const std::vector<PeriodicWaveforms>& FFBDevice::availableWaveformsList() const
{
- QStringList list;
-
- for (const PeriodicWaveforms w : m_availablePeriodicWaveforms)
- list << waveformName(w);
-
- return list;
-}
-
-QString FFBDevice::conditionSubtypeName(const ConditionSubtypes subtype) const
-{
- switch (subtype) {
- case ConditionSubtypes::DAMPER:
- return "Damper";
- case ConditionSubtypes::FRICTION:
- return "Friction";
- case ConditionSubtypes::INERTIA:
- return "Inertia";
- case ConditionSubtypes::SPRING:
- return "Spring";
- default:
- return "Unknown subtype";
- }
-}
-
-QString FFBDevice::effectName(const FFBEffectTypes effect) const
-{
- switch (effect) {
- case FFBEffectTypes::CONSTANT:
- return "Constant force";
- case FFBEffectTypes::PERIODIC:
- return "Periodic force";
- case FFBEffectTypes::RAMP:
- return "Ramp";
- case FFBEffectTypes::CONDITION:
- return "Condition";
- case FFBEffectTypes::RUMBLE:
- return "Rumble";
- default:
- return "Unknown effect";
- }
+ return m_availablePeriodicWaveforms;
}
const std::shared_ptr<FFBEffectParameters> FFBDevice::effectParameters(const int idx)
return m_effects[idx]->type();
}
-unsigned int FFBDevice::effectTypeToIdx(FFBEffectTypes type)
-{
- for (unsigned int i = 0; i < m_availableEffects.size(); i++) {
- if (m_availableEffects[i] == type)
- return i;
- }
- qWarning() << "Effect type no found in the list!";
- return 0;
-}
-
-QString FFBDevice::waveformName(const PeriodicWaveforms waveform) const
-{
- switch (waveform) {
- case PeriodicWaveforms::SQUARE:
- return "Square";
- case PeriodicWaveforms::TRIANGLE:
- return "Triangle";
- case PeriodicWaveforms::SINE:
- return "Sine";
- case PeriodicWaveforms::SAW_UP:
- return "Saw up";
- case PeriodicWaveforms::SAW_DOWN:
- return "Saw down";
- default:
- return "Unknown waveform";
- }
-}
-
bool FFBDevice::hasEffect(FFBEffectTypes id) const
{
for (const FFBEffectTypes e : m_availableEffects)
bool FFBDevice::startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> parameters)
{
int ret;
- std::shared_ptr<FFBEffect> effect;
CHECK_EFFECT_IDX(idx);
- effect = m_effects[idx];
-
- if (effect->status() == FFBEffect::FFBEffectStatus::NOT_LOADED) {
+ if (m_effects[idx]->status() == FFBEffect::FFBEffectStatus::NOT_LOADED) {
if (!uploadEffect(idx, type, parameters))
return false;
}
- if (effect->status() == FFBEffect::FFBEffectStatus::PLAYING)
+ if (m_effects[idx]->status() == FFBEffect::FFBEffectStatus::PLAYING)
return true;
/* Start playback */
struct input_event evt;
evt.type = EV_FF;
- evt.code = effect->internalIdx();
- evt.value = effect->parameters()->repeat;
+ evt.code = m_effects[idx]->internalIdx();
+ evt.value = m_effects[idx]->parameters()->repeat;
ret = write(c_fd, &evt, sizeof(struct input_event));
if (ret != sizeof(struct input_event)) {
return false;
}
- effect->setStatus(FFBEffect::FFBEffectStatus::PLAYING);
+ m_effects[idx]->setStatus(FFBEffect::FFBEffectStatus::PLAYING);
return true;
}
public:
explicit FFBDevice(const int fd, const QString& path, const int maxEffectCount, QObject* parent = 0);
- QStringList availableConditionSubtypesList() const;
- QStringList availableEffectsList() const;
- QStringList availableWaveformsList() const;
- inline ConditionSubtypes conditionSubtypeByIdx(const int idx) { return m_availableConditionSubtypes[idx]; }
- QString conditionSubtypeName(const ConditionSubtypes subtype) const;
- QString effectName(const FFBEffectTypes effect) const;
+ const std::vector<ConditionSubtypes>& availableConditionSubtypesList() const;
+ const std::vector<FFBEffectTypes>& availableEffectsList() const;
+ const std::vector<PeriodicWaveforms>& availableWaveformsList() const;
const std::shared_ptr<FFBEffectParameters> effectParameters(const int idx);
FFBEffect::FFBEffectStatus effectStatusByIdx(const int idx) const;
- inline FFBEffectTypes effectTypeFromSelectionIdx(const int idx) const { return m_availableEffects[idx]; }
- unsigned int effectTypeToIdx(FFBEffectTypes type);
FFBEffectTypes effectTypeByEffectIdx(const int idx) const;
bool hasEffect(FFBEffectTypes id) const;
bool hasPeriodicWaveform(PeriodicWaveforms id) const;
bool startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> parameters);
bool stopEffect(const int idx);
bool uploadEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> parameters);
- QString waveformName(const PeriodicWaveforms waveform) const;
inline PeriodicWaveforms waveformByIdx(const int idx) const { return m_availablePeriodicWaveforms[idx]; }
private:
}
}
+QString MainWindow::effectTypeToEffectName(const FFBEffectTypes etype) const
+{
+ switch (etype) {
+ case FFBEffectTypes::CONSTANT:
+ return "Constant force";
+ case FFBEffectTypes::PERIODIC:
+ return "Periodic force";
+ case FFBEffectTypes::RAMP:
+ return "Ramp";
+ case FFBEffectTypes::CONDITION:
+ return "Condition";
+ case FFBEffectTypes::RUMBLE:
+ return "Rumble";
+ default:
+ return "Unknown effect";
+ }
+}
+
void MainWindow::fillDeviceList()
{
ui->cbox_devices->clear();
ui->cbox_devices->addItem(dinfo.tag, dinfo.path);
}
-void MainWindow::fillEffectSlotsList(const int idx)
+void MainWindow::fillEffectSlotsList(const int effectCount)
{
ui->cbox_effectSlots->clear();
- for (int i = 1; i <= idx; i++)
- ui->cbox_effectSlots->addItem(QString::number(i));
+ for (int i = 1; i <= effectCount; i++)
+ ui->cbox_effectSlots->addItem(QString::number(i), i-1);
}
-void MainWindow::fillEffectTypesList(const QStringList& list)
+void MainWindow::fillEffectTypesList(const std::vector<FFBEffectTypes>& list)
{
ui->cbox_effectTypes->clear();
- ui->cbox_effectTypes->addItems(list);
+ for (const FFBEffectTypes etype : list)
+ ui->cbox_effectTypes->addItem(effectTypeToEffectName(etype), static_cast<std::underlying_type<FFBEffectTypes>::type>(etype));
}
-void MainWindow::onDeviceSelected(const int idx)
+void MainWindow::onDeviceSelected(const int cboxIdx)
{
- QString path = ui->cbox_devices->itemData(idx, Qt::UserRole).toString();
+ Q_UNUSED(cboxIdx);
+
+ QString path = ui->cbox_devices->currentData(Qt::UserRole).toString();
ui->cbox_effectSlots->clear();
m_activeDevice = m_prober->openDevice(path);
fillEffectTypesList(m_activeDevice->availableEffectsList());
m_conditionEffSet->fillAvailableSubtypesList(m_activeDevice->availableConditionSubtypesList());
m_periodicEffSet->fillAvailableWaveformsList(m_activeDevice->availableWaveformsList());
+ ui->cbox_effectSlots->setCurrentIndex(0);
onEffectSlotSelected(0);
}
-void MainWindow::onEffectSlotSelected(const int idx)
+void MainWindow::onEffectSlotSelected(const int cboxIdx)
{
- if (idx < 0)
- return;
+ int effectIdx;
+ bool ok;
+
+ Q_UNUSED(cboxIdx);
+
if (m_activeDevice == nullptr)
return;
- FFBEffectTypes type = m_activeDevice->effectTypeByEffectIdx(idx);
- qDebug() << static_cast<int>(type);
- if (type == FFBEffectTypes::NONE) {
+ effectIdx = ui->cbox_effectSlots->currentData(Qt::UserRole).toInt(&ok);
+ if (!ok) {
+ QMessageBox::critical(this, "Runtime error", "Nonsensical data passed as effect slot index.");
+ return;
+ }
+ FFBEffectTypes etype = m_activeDevice->effectTypeByEffectIdx(effectIdx);
+ qDebug() << static_cast<int>(etype);
+ if (etype == FFBEffectTypes::NONE) {
qDebug() << "Empty effect";
- ui->cbox_effectTypes->setCurrentIndex(0);
- ui->qstw_effectSpecifics->setCurrentWidget(effectSettingsByType(m_activeDevice->effectTypeFromSelectionIdx(0)));
+ setEffectTypeIndexByType(etype);
+ ui->qstw_effectSpecifics->setCurrentWidget(effectSettingsByType(FFBEffectTypes::CONSTANT));
setEffectStatusText(FFBEffect::FFBEffectStatus::NOT_LOADED);
return;
}
- const std::shared_ptr<FFBEffectParameters> params = m_activeDevice->effectParameters(idx);
+ const std::shared_ptr<FFBEffectParameters> params = m_activeDevice->effectParameters(effectIdx);
/* Set global parameters */
ui->qle_direction->setText(QString::number(params->direction));
ui->qle_replayDelay->setText(QString::number(params->replayDelay));
ui->qle_replayLength->setText(QString::number(params->replayLength));
- EffectSettings* efs = effectSettingsByType(type);
+ EffectSettings* efs = effectSettingsByType(etype);
if (!efs->fillFromParameters(params))
QMessageBox::warning(this, "UI error", "Unable to read effect parameters.");
- ui->cbox_effectTypes->setCurrentIndex(m_activeDevice->effectTypeToIdx(type));
+ setEffectTypeIndexByType(etype);
ui->qstw_effectSpecifics->setCurrentWidget(efs);
- setEffectStatusText(m_activeDevice->effectStatusByIdx(idx));
+ setEffectStatusText(m_activeDevice->effectStatusByIdx(effectIdx));
}
-void MainWindow::onEffectTypeSelected(const int idx)
+void MainWindow::onEffectTypeSelected(const int cboxIdx)
{
- if (idx < 0)
- return;
+ Q_UNUSED(cboxIdx);
+
if (m_activeDevice == nullptr)
return;
- ui->qstw_effectSpecifics->setCurrentWidget(effectSettingsByType(m_activeDevice->effectTypeFromSelectionIdx(idx)));
+ FFBEffectTypes etype = *static_cast<FFBEffectTypes*>(ui->cbox_effectTypes->currentData(Qt::UserRole).data());
+ ui->qstw_effectSpecifics->setCurrentWidget(effectSettingsByType(etype));
}
void MainWindow::onRefreshDevicesClicked()
void MainWindow::onStartEffectClicked()
{
+ bool ok;
+ int effectSlot;
+
if (m_activeDevice == nullptr)
return;
- FFBEffectTypes type = m_activeDevice->effectTypeFromSelectionIdx(ui->cbox_effectTypes->currentIndex());
+ FFBEffectTypes etype = *static_cast<FFBEffectTypes*>(ui->cbox_effectTypes->currentData(Qt::UserRole).data());
std::shared_ptr<FFBEffectParameters> params;
- int effectSlot = ui->cbox_effectSlots->currentIndex();
- if (!readEffectParameters(params, type)) {
+ effectSlot = ui->cbox_effectSlots->currentData().toInt(&ok);
+ if (!ok) {
+ QMessageBox::critical(this, "Runtime error", "Nonsensical data passed as effect slot index.");
+ return;
+ }
+
+ if (!readEffectParameters(params, etype)) {
qDebug() << "Cannot read effect params.";
return;
}
- bool ret = m_activeDevice->startEffect(effectSlot, type, params);
+ bool ret = m_activeDevice->startEffect(effectSlot, etype, params);
if (ret)
setEffectStatusText(m_activeDevice->effectStatusByIdx(effectSlot));
else
void MainWindow::onStopEffectClicked()
{
+ int effectSlot;
+ bool ok;
+
if (m_activeDevice == nullptr)
return;
- int effectSlot = ui->cbox_effectSlots->currentIndex();
+ effectSlot = ui->cbox_effectSlots->currentData().toInt(&ok);
+ if (!ok) {
+ QMessageBox::critical(this, "Runtime error", "Nonsensical data passed as effect slot index.");
+ return;
+ }
m_activeDevice->stopEffect(effectSlot);
setEffectStatusText(m_activeDevice->effectStatusByIdx(effectSlot));
}
void MainWindow::onUploadEffectClicked()
{
+ bool ok;
+ int effectSlot;
+
if (m_activeDevice == nullptr)
return;
- FFBEffectTypes type = m_activeDevice->effectTypeFromSelectionIdx(ui->cbox_effectTypes->currentIndex());
+ FFBEffectTypes etype = *static_cast<FFBEffectTypes*>(ui->cbox_effectTypes->currentData(Qt::UserRole).data());
std::shared_ptr<FFBEffectParameters> params;
- int effectSlot = ui->cbox_effectSlots->currentIndex();
+ effectSlot = ui->cbox_effectSlots->currentData().toInt(&ok);
+ if (!ok) {
+ QMessageBox::critical(this, "Runtime error", "Nonsensical data passed as effect slot index.");
+ return;
+ }
- if (!readEffectParameters(params, type)) {
+ if (!readEffectParameters(params, etype)) {
qDebug() << "Cannot read effect params.";
return;
}
- bool ret = m_activeDevice->uploadEffect(effectSlot, type, params);
+ bool ret = m_activeDevice->uploadEffect(effectSlot, etype, params);
if (ret)
setEffectStatusText(m_activeDevice->effectStatusByIdx(effectSlot));
else
return false;
}
- ConditionSubtypes subtype = m_activeDevice->conditionSubtypeByIdx(m_conditionEffSet->subtypeIdx());
- iParams->subtypeFromIdx(subtype);
+ ConditionSubtypes subtype = m_conditionEffSet->subtype();
+ iParams->subtype = subtype;
params = iParams;
break;
}
}
+void MainWindow::setEffectTypeIndexByType(const FFBEffectTypes etype)
+{
+ for (int idx = 0; idx < ui->cbox_effectTypes->count(); idx++) {
+ FFBEffectTypes ietype = *static_cast<FFBEffectTypes*>(ui->cbox_effectTypes->itemData(idx, Qt::UserRole).data());
+ if (ietype == etype) {
+ ui->cbox_effectTypes->setCurrentIndex(idx);
+ return;
+ }
+ }
+}
+
MainWindow::~MainWindow()
{
delete ui;
private:
EffectSettings* effectSettingsByType(FFBEffectTypes type);
+ QString effectTypeToEffectName(const FFBEffectTypes type) const;
void fillDeviceList();
- void fillEffectSlotsList(const int idx);
- void fillEffectTypesList(const QStringList& list);
+ void fillEffectSlotsList(const int effectCount);
+ void fillEffectTypesList(const std::vector<FFBEffectTypes>& list);
bool readEnvelopeParameters(std::shared_ptr<FFBEnvelopeParameters> params, const EnvelopeSettings* es);
- bool readEffectParameters(std::shared_ptr<FFBEffectParameters>& params, FFBEffectTypes type);
+ bool readEffectParameters(std::shared_ptr<FFBEffectParameters>& params, FFBEffectTypes etype);
bool readGeneralEffectParameters(std::shared_ptr<FFBEffectParameters> params);
void setEffectStatusText(const FFBEffect::FFBEffectStatus status);
+ void setEffectTypeIndexByType(const FFBEffectTypes etype);
std::shared_ptr<FFBDevice> m_activeDevice;
ConditionEffectSettings* m_conditionEffSet;
static const QString res_inputFormatErrCap;
private slots:
- void onDeviceSelected(const int idx);
- void onEffectSlotSelected(const int idx);
- void onEffectTypeSelected(const int idx);
+ void onDeviceSelected(const int cboxIdx);
+ void onEffectSlotSelected(const int cboxIdx);
+ void onEffectTypeSelected(const int cboxIdx);
void onRefreshDevicesClicked();
void onRemoveEffectClicked();
void onStartEffectClicked();
return ui->qwid_envelope;
}
-void PeriodicEffectSettings::fillAvailableWaveformsList(const QStringList& list)
+void PeriodicEffectSettings::fillAvailableWaveformsList(const std::vector<PeriodicWaveforms>& list)
{
ui->cbox_waveform->clear();
- ui->cbox_waveform->addItems(list);
+ for (const PeriodicWaveforms waveform : list)
+ ui->cbox_waveform->addItem(waveformTypeToWaveformName(waveform), static_cast<std::underlying_type<PeriodicWaveforms>::type>(waveform));
}
bool PeriodicEffectSettings::fillFromParameters(const std::shared_ptr<FFBEffectParameters> params)
return ui->qle_phase->text();
}
+QString PeriodicEffectSettings::waveformTypeToWaveformName(const PeriodicWaveforms waveform) const
+{
+ switch (waveform) {
+ case PeriodicWaveforms::SQUARE:
+ return "Square";
+ case PeriodicWaveforms::TRIANGLE:
+ return "Triangle";
+ case PeriodicWaveforms::SINE:
+ return "Sine";
+ case PeriodicWaveforms::SAW_UP:
+ return "Saw up";
+ case PeriodicWaveforms::SAW_DOWN:
+ return "Saw down";
+ default:
+ return "Unknown waveform";
+ }
+}
+
int PeriodicEffectSettings::waveformIdx() const
{
return ui->cbox_waveform->currentIndex();
explicit PeriodicEffectSettings(QWidget* parent = 0);
~PeriodicEffectSettings();
const EnvelopeSettings* envelopeSettings() const;
- void fillAvailableWaveformsList(const QStringList& list);
+ void fillAvailableWaveformsList(const std::vector<PeriodicWaveforms>& list);
bool fillFromParameters(const std::shared_ptr<FFBEffectParameters> params);
QString magnitude() const;
QString offset() const;
QString period() const;
QString phase() const;
+ QString waveformTypeToWaveformName(const PeriodicWaveforms waveform) const;
int waveformIdx() const;
private: