#include <QtWidgets/QMessageBox>
#include <QDebug>
+#define CHECK_EFFECT_IDX(idx) if (idx < 0 || idx > c_maxEffectCount) return false
+
const quint8 FFBDevice::BITS_PER_LONG = sizeof(unsigned long) * 8;
FFBDevice::FFBDevice(const int fd, const QString& path, const int maxEffectCount, QObject* parent) :
return true;
}
-bool FFBDevice::startEffect(const int idx, FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> params)
+bool FFBDevice::startEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> parameters)
{
- bool dontStart = false;
- std::shared_ptr<FFBEffect> effect = FFBEffectFactory::createEffect(type);
- if (effect == nullptr) {
- qDebug() << "Unable to create effect";
- return false;
- }
- if (!effect->setParameters(params)) {
- qDebug() << "Unable to set effect parameters, some values are probably invalid.";
- return false;
- }
+ int ret;
+ std::shared_ptr<FFBEffect> effect;
- if (idx < 0 || idx > c_maxEffectCount) {
- qCritical() << "Effect index out of bounds";
- return false;
- }
+ CHECK_EFFECT_IDX(idx);
- /* There is no effect in the selected slot */
- if (m_effects[idx]->type() == FFBEffectTypes::NONE) {
- qDebug() << "Creating new effect";
- } else {
- if (*m_effects[idx] != *effect) {
- removeEffect(idx);
- qDebug() << "Recreating effect" << idx;
- } else {
- effect->setInternalIdx(m_effects[idx]->internalIdx());
- effect->setStatus(m_effects[idx]->status());
- if (effect->status() == FFBEffect::FFBEffectStatus::PLAYING) {
- dontStart = true;
- }
- qDebug() << "Updating effect" << idx;
- }
- }
- m_effects[idx] = effect;
-
- struct ff_effect* kernelEff = nullptr;
- kernelEff = m_effects[idx]->createFFStruct();
- if (kernelEff == nullptr) {
- QMessageBox::critical(nullptr, "FFB Device", "ff_effect struct could not have been created. Effect not uploaded.");
- qDebug() << "struct ff_effect not created";
- return false;
- }
-
- qDebug() << kernelEff->u.condition[0].center << kernelEff->u.condition[0].deadband << kernelEff->u.condition[1].center << kernelEff->u.condition[1].deadband;
+ effect = m_effects[idx];
- int ret = uploadEffect(kernelEff);
- if (ret < 0) {
- QMessageBox::critical(nullptr, "FFB Device", "Effect could not have been uploaded, error code: " + QString::number(ret));
- qDebug() << "Effect not uploaded" << ret;
- delete kernelEff;
- return false;
+ if (effect->status() == FFBEffect::FFBEffectStatus::NOT_LOADED) {
+ if (!uploadEffect(idx, type, parameters))
+ return false;
}
- if (dontStart)
+ if (effect->status() == FFBEffect::FFBEffectStatus::PLAYING)
return true;
- m_effects[idx]->setInternalIdx(kernelEff->id);
- m_effects[idx]->setStatus(FFBEffect::FFBEffectStatus::STOPPED);
-
/* Start playback */
struct input_event evt;
evt.type = EV_FF;
- evt.code = kernelEff->id;
- evt.value = m_effects[idx]->parameters()->repeat;
+ evt.code = effect->internalIdx();
+ evt.value = effect->parameters()->repeat;
ret = write(c_fd, &evt, sizeof(struct input_event));
if (ret != sizeof(struct input_event)) {
QMessageBox::critical(nullptr, "FFB Device", "Effect could not have been started, error code: " + QString::number(ret));
qDebug() << "Effect not started" << ret;
- delete kernelEff;
return false;
}
- m_effects[idx]->setStatus(FFBEffect::FFBEffectStatus::PLAYING);
+ effect->setStatus(FFBEffect::FFBEffectStatus::PLAYING);
- delete kernelEff;
return true;
}
bool FFBDevice::stopEffect(const int idx)
{
+ CHECK_EFFECT_IDX(idx);
+
if (m_effects[idx] == nullptr)
return true;
if (ret != sizeof(struct input_event))
return false;
- m_effects[idx]->setStatus(FFBEffect::FFBEffectStatus::STOPPED);
+ m_effects[idx]->setStatus(FFBEffect::FFBEffectStatus::UPLOADED);
return true;
}
-int FFBDevice::uploadEffect(struct ff_effect* effect)
+bool FFBDevice::uploadEffect(const int idx, const FFBEffectTypes type, std::shared_ptr<FFBEffectParameters> parameters)
{
- int ret = ioctl(c_fd, EVIOCSFF, effect);
+ struct ff_effect* kernelEff = nullptr;
+ std::shared_ptr<FFBEffect> effect = FFBEffectFactory::createEffect(type);
+
+ CHECK_EFFECT_IDX(idx);
+
+ if (effect == nullptr) {
+ qDebug() << "Unable to create effect";
+ return false;
+ }
+ if (!effect->setParameters(parameters)) {
+ qDebug() << "Unable to set effect parameters, some values are probably invalid.";
+ return false;
+ }
+
+ if (idx < 0 || idx > c_maxEffectCount) {
+ qCritical() << "Effect index out of bounds";
+ return false;
+ }
+
+ /* There is no effect in the selected slot */
+ if (m_effects[idx]->type() == FFBEffectTypes::NONE) {
+ effect->setStatus(FFBEffect::FFBEffectStatus::UPLOADED);
+ qDebug() << "Creating new effect";
+ } else {
+ if (*m_effects[idx] != *effect) {
+ if (!removeEffect(idx)) {
+ QMessageBox::critical(nullptr, "FFB Device", "Unable to remove effect");
+ return false;
+ }
+ effect->setStatus(FFBEffect::FFBEffectStatus::UPLOADED);
+ qDebug() << "Recreating effect" << idx;
+ } else {
+ effect->setInternalIdx(m_effects[idx]->internalIdx());
+ effect->setStatus(m_effects[idx]->status());
+ qDebug() << "Updating effect" << idx;
+ }
+ }
+
+ kernelEff = effect->createFFStruct();
+ if (kernelEff == nullptr) {
+ QMessageBox::critical(nullptr, "FFB Device", "ff_effect struct could not have been created. Effect not uploaded.");
+ qDebug() << "struct ff_effect not created";
+ return false;
+ }
+
+ qDebug() << kernelEff->u.condition[0].center << kernelEff->u.condition[0].deadband << kernelEff->u.condition[1].center << kernelEff->u.condition[1].deadband;
+
+ int ret = ioctl(c_fd, EVIOCSFF, kernelEff);
if (ret < 0) {
- qDebug() << "Error while uploading effect";
- return ret;
+ QMessageBox::critical(nullptr, "FFB Device", "Effect could not have been uploaded, error code: " + QString::number(ret));
+ qDebug() << "Effect not uploaded" << ret;
+ delete kernelEff;
+ return false;
}
- return effect->id;
+ effect->setInternalIdx(kernelEff->id);
+ delete kernelEff;
+
+ m_effects[idx] = effect;
+ return true;
}
const QString MainWindow::res_deviceErrorCap("Device error");
const QString MainWindow::res_effectNotLoaded("Not loaded");
const QString MainWindow::res_effectPlaying("Playing");
-const QString MainWindow::res_effectStopped("Stopped");
+const QString MainWindow::res_effectUploaded("Uploaded");
const QString MainWindow::res_inputFormatErrCap("Invalid input format.");
MainWindow::MainWindow(std::shared_ptr<DeviceProber> prober, const QString& title, QWidget* parent) :
connect(ui->qpb_remove, SIGNAL(clicked()), this, SLOT(onRemoveEffectClicked()));
connect(ui->qpb_start, SIGNAL(clicked()), this, SLOT(onStartEffectClicked()));
connect(ui->qpb_stop, SIGNAL(clicked()), this, SLOT(onStopEffectClicked()));
+ connect(ui->qpb_upload, SIGNAL(clicked()), this, SLOT(onUploadEffectClicked()));
}
EffectSettings* MainWindow::effectSettingsByType(FFBEffectTypes type)
setEffectStatusText(m_activeDevice->effectStatusByIdx(effectSlot));
}
+void MainWindow::onUploadEffectClicked()
+{
+ if (m_activeDevice == nullptr)
+ return;
+
+ FFBEffectTypes type = m_activeDevice->effectTypeFromSelectionIdx(ui->cbox_effectTypes->currentIndex());
+ std::shared_ptr<FFBEffectParameters> params;
+ int effectSlot = ui->cbox_effectSlots->currentIndex();
+
+ if (!readEffectParameters(params, type)) {
+ qDebug() << "Cannot read effect params.";
+ return;
+ }
+ bool ret = m_activeDevice->uploadEffect(effectSlot, type, params);
+ if (ret)
+ setEffectStatusText(m_activeDevice->effectStatusByIdx(effectSlot));
+ else
+ QMessageBox::warning(this, res_deviceErrorCap, "Unable to upload the effect.");
+}
+
bool MainWindow::readEnvelopeParameters(std::shared_ptr<FFBEnvelopeParameters> params, const EnvelopeSettings* es)
{
if (!params->attackLengthFromString(es->attackLength())) {
case FFBEffect::FFBEffectStatus::PLAYING:
ui->ql_effectStatus->setText(res_effectPlaying);
break;
- case FFBEffect::FFBEffectStatus::STOPPED:
- ui->ql_effectStatus->setText(res_effectStopped);
+ case FFBEffect::FFBEffectStatus::UPLOADED:
+ ui->ql_effectStatus->setText(res_effectUploaded);
break;
}
}