Skip to content

Commit

Permalink
feat: add command line vibrate command
Browse files Browse the repository at this point in the history
  • Loading branch information
jahnf committed Oct 17, 2023
1 parent 5763302 commit 64ddea6
Show file tree
Hide file tree
Showing 8 changed files with 185 additions and 45 deletions.
53 changes: 27 additions & 26 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -108,32 +108,33 @@ else()
endif()

add_executable(projecteur
src/main.cc src/enum-helper.h
src/aboutdlg.cc src/aboutdlg.h
src/actiondelegate.cc src/actiondelegate.h
src/colorselector.cc src/colorselector.h
src/device.cc src/device.h
src/device-hidpp.cc src/device-hidpp.h
src/device-key-lookup.cc src/device-key-lookup.h
src/device-vibration.cc src/device-vibration.h
src/deviceinput.cc src/deviceinput.h
src/devicescan.cc src/devicescan.h
src/deviceswidget.cc src/deviceswidget.h
src/hidpp.cc src/hidpp.h
src/linuxdesktop.cc src/linuxdesktop.h
src/iconwidgets.cc src/iconwidgets.h
src/imageitem.cc src/imageitem.h
src/inputmapconfig.cc src/inputmapconfig.h
src/inputseqedit.cc src/inputseqedit.h
src/logging.cc src/logging.h
src/nativekeyseqedit.cc src/nativekeyseqedit.h
src/preferencesdlg.cc src/preferencesdlg.h
src/projecteurapp.cc src/projecteurapp.h
src/runguard.cc src/runguard.h
src/settings.cc src/settings.h
src/spotlight.cc src/spotlight.h
src/spotshapes.cc src/spotshapes.h
src/virtualdevice.h src/virtualdevice.cc
src/main.cc src/enum-helper.h
src/aboutdlg.cc src/aboutdlg.h
src/actiondelegate.cc src/actiondelegate.h
src/colorselector.cc src/colorselector.h
src/device.cc src/device.h
src/device-command-helper.cc src/device-command-helper.h
src/device-hidpp.cc src/device-hidpp.h
src/device-key-lookup.cc src/device-key-lookup.h
src/device-vibration.cc src/device-vibration.h
src/deviceinput.cc src/deviceinput.h
src/devicescan.cc src/devicescan.h
src/deviceswidget.cc src/deviceswidget.h
src/hidpp.cc src/hidpp.h
src/linuxdesktop.cc src/linuxdesktop.h
src/iconwidgets.cc src/iconwidgets.h
src/imageitem.cc src/imageitem.h
src/inputmapconfig.cc src/inputmapconfig.h
src/inputseqedit.cc src/inputseqedit.h
src/logging.cc src/logging.h
src/nativekeyseqedit.cc src/nativekeyseqedit.h
src/preferencesdlg.cc src/preferencesdlg.h
src/projecteurapp.cc src/projecteurapp.h
src/runguard.cc src/runguard.h
src/settings.cc src/settings.h
src/spotlight.cc src/spotlight.h
src/spotshapes.cc src/spotshapes.h
src/virtualdevice.cc src/virtualdevice.h
${RESOURCES})

target_include_directories(projecteur PRIVATE src)
Expand Down
52 changes: 36 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,39 @@ So here it is: a Linux application for the Logitech Spotlight.

## Table of Contents

* [Motivation](#motivation)
* [Features](#features)
* [Supported Environments](#supported-environments)
* [How it works](#how-it-works)
* [Download](#download)
* [Building](#building)
* [Installation/Running](#installationrunning)
* [Pre-requisites](#pre-requisites)
* [Application Menu](#application-menu)
* [Command Line Interface](#command-line-interface)
* [Scriptability / Keyboard shortcuts](#scriptability)
* [Using Projecteur without a device](#using-projecteur-without-a-device)
* [Device Support](#device-support)
* [Troubleshooting](#troubleshooting)
* [Changelog](#changelog)
* [License](#license)
- [Projecteur](#projecteur)
- [Motivation](#motivation)
- [Table of Contents](#table-of-contents)
- [Features](#features)
- [Screenshots](#screenshots)
- [Planned features](#planned-features)
- [Supported Environments](#supported-environments)
- [How it works](#how-it-works)
- [Button mapping](#button-mapping)
- [Hold Button Mapping for Logitech Spotlight](#hold-button-mapping-for-logitech-spotlight)
- [Download](#download)
- [Building](#building)
- [Requirements](#requirements)
- [Build Example](#build-example)
- [Installation/Running](#installationrunning)
- [Pre-requisites](#pre-requisites)
- [When building Projecteur yourself](#when-building-projecteur-yourself)
- [Application Menu](#application-menu)
- [Command Line Interface](#command-line-interface)
- [Scriptability](#scriptability)
- [Using Projecteur without a device](#using-projecteur-without-a-device)
- [Device Support](#device-support)
- [Compile Time](#compile-time)
- [Runtime](#runtime)
- [Troubleshooting](#troubleshooting)
- [Opaque Spotlight / No Transparency](#opaque-spotlight--no-transparency)
- [Missing System Tray](#missing-system-tray)
- [Zoom is not updated while spotlight is shown](#zoom-is-not-updated-while-spotlight-is-shown)
- [Wayland](#wayland)
- [Wayland Zoom](#wayland-zoom)
- [Device shows as not connected](#device-shows-as-not-connected)
- [Changelog](#changelog)
- [License](#license)

## Features

Expand Down Expand Up @@ -250,6 +267,9 @@ Example:
projecteur -c border=true
# Set the border color to red
projecteur -c border.color=#ff0000
# Send a vibrate command to the device with
# intensity=128 and length=0 (only Logitech Spotlight)
projecteur -c vibrate=128,0
```

While _Projecteur_ does not provide global keyboard shortcuts, command line options
Expand Down
2 changes: 1 addition & 1 deletion cmake/templates/projecteur.bash-completion
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ _projecteur()
case "$prev" in
"-c")
# Auto completion for commands and properties
local commands="quit spot= spot.size.adjust= settings= preset="
local commands="quit spot= spot.size.adjust= settings= preset= vibrate="
commands="${commands} spot.size= spot.rotation= spot.shape= spot.shape.square.radius="
commands="${commands} spot.multi-screen= spot.overlay="
commands="${commands} spot.shape.star.points= spot.shape.star.innerradius= spot.shape.ngon.sides="
Expand Down
52 changes: 52 additions & 0 deletions src/device-command-helper.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// This file is part of Projecteur - https://github.com/jahnf/projecteur
// - See LICENSE.md and README.md

#include "device-command-helper.h"

#include "device-hidpp.h"
#include "spotlight.h"

// -------------------------------------------------------------------------------------------------
DeviceCommandHelper::DeviceCommandHelper(QObject* parent, Spotlight* spotlight)
: QObject(parent), m_spotlight(spotlight)
{

}

// -------------------------------------------------------------------------------------------------
DeviceCommandHelper::~DeviceCommandHelper() = default;


// -------------------------------------------------------------------------------------------------
bool DeviceCommandHelper::sendVibrateCommand(uint8_t intensity, uint8_t length)
{
if (m_spotlight.isNull()) {
return false;
}

for ( auto const& dev : m_spotlight->connectedDevices()) {
if (auto connection = m_spotlight->deviceConnection(dev.id)) {
if (!connection->hasHidppSupport()) {
continue;
}

for (auto const& subInfo : connection->subDevices()) {
auto const& subConn = subInfo.second;
if (!subConn || !subConn->hasFlags(DeviceFlag::Vibrate)) {
continue;
}

if (auto hidppConn = std::dynamic_pointer_cast<SubHidppConnection>(subConn))
{
hidppConn->sendVibrateCommand(intensity, length,
[](HidppConnectionInterface::MsgResult, HIDPP::Message&&) {
// logDebug(hid) << tr("Vibrate command returned: %1 (%2)")
// .arg(toString(result)).arg(msg.hex());
});
}
}
}
}

return true;
}
24 changes: 24 additions & 0 deletions src/device-command-helper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// This file is part of Projecteur - https://github.com/jahnf/projecteur
// - See LICENSE.md and README.md
#pragma once

#include <QObject>
#include <QPointer>

class Spotlight;

/// Class that offers easy access to device commands with a given Spotlight
/// instance.
class DeviceCommandHelper : public QObject
{
Q_OBJECT

public:
explicit DeviceCommandHelper(QObject* parent, Spotlight* spotlight);
virtual ~DeviceCommandHelper();

bool sendVibrateCommand(uint8_t intensity, uint8_t length);

private:
QPointer<Spotlight> m_spotlight;
};
1 change: 1 addition & 0 deletions src/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ namespace {
print() << " settings=[show|hide] " << Main::tr("Show/hide preferences dialog.");
if (fullHelp) {
print() << " preset=NAME " << Main::tr("Set a preset.");
print() << " vibrate[=I[,L]] " << Main::tr("Send vibrate command to device with intensity,length.");
}
print() << " quit " << Main::tr("Quit the running instance.");

Expand Down
39 changes: 39 additions & 0 deletions src/projecteurapp.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "projecteurapp.h"

#include "aboutdlg.h"
#include "device-command-helper.h"
#include "imageitem.h"
#include "linuxdesktop.h"
#include "logging.h"
Expand Down Expand Up @@ -68,6 +69,8 @@ ProjecteurApplication::ProjecteurApplication(int &argc, char **argv, const Optio
m_spotlight = new Spotlight(this, Spotlight::Options{options.enableUInput, options.additionalDevices},
m_settings);

m_deviceCommandHelper = new DeviceCommandHelper(this, m_spotlight);

m_settings->setOverlayDisabled(options.disableOverlay);
m_dialog = std::make_unique<PreferencesDialog>(m_settings, m_spotlight,
options.dialogMinimizeOnly
Expand Down Expand Up @@ -586,6 +589,42 @@ void ProjecteurApplication::readCommand(QLocalSocket* clientConnection)
logDebug(cmdserver) << tr("Received quit command.");
this->quit();
}
else if (cmdKey == "vibrate") // with args intensity (0-255), length (0-10)
{
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
auto const args = cmdValue.split(QLatin1Char(','), Qt::SkipEmptyParts);
#else
auto const args = cmdValue.split(QLatin1Char(','), QString::SkipEmptyParts);
#endif

std::uint8_t const intensity = [&args]{
if (args.size() >= 1) {
bool ok = false;
auto intensity = args[0].toInt(&ok);
if (ok) {
return static_cast<std::uint8_t>(qMin(255, qMax(0, intensity)));
}
}
return std::uint8_t{128};
}();

std::uint8_t const length = [&args]{
if (args.size() >= 2) {
bool ok = false;
auto intensity = args[1].toInt(&ok);
if (ok) {
return static_cast<std::uint8_t>(qMin(10, qMax(0, intensity)));
}
}
return std::uint8_t{0};
}();

logDebug(cmdserver) << tr("Received command vibrate = intensity:%1, length:%2")
.arg(intensity)
.arg(length);

m_deviceCommandHelper->sendVibrateCommand(intensity, length);
}
else if (cmdKey == "spot.size.adjust")
{
bool ok = false;
Expand Down
7 changes: 5 additions & 2 deletions src/projecteurapp.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// - See LICENSE.md and README.md
#pragma once

#include "spotlight.h"
#include "devicescan.h"

#include <QApplication>
#include <QPointer>
Expand All @@ -11,6 +11,7 @@
#include <memory>

class AboutDialog;
class DeviceCommandHelper;
class LinuxDesktop;
class PreferencesDialog;
class QLocalServer;
Expand All @@ -20,6 +21,7 @@ class QQmlApplicationEngine;
class QQmlComponent;
class QSystemTrayIcon;
class Settings;
class Spotlight;

class ProjecteurApplication : public QApplication
{
Expand Down Expand Up @@ -78,8 +80,9 @@ private slots:
std::unique_ptr<PreferencesDialog> m_dialog;
QPointer<AboutDialog> m_aboutDialog;
QLocalServer* const m_localServer = nullptr;
Spotlight* m_spotlight = nullptr;
Settings* m_settings = nullptr;
Spotlight* m_spotlight = nullptr;
DeviceCommandHelper* m_deviceCommandHelper = nullptr;
LinuxDesktop* m_linuxDesktop = nullptr;
QQmlApplicationEngine* m_qmlEngine = nullptr;
QQmlComponent* m_windowQmlComponent = nullptr;
Expand Down

0 comments on commit 64ddea6

Please sign in to comment.