Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add command line vibrate command #211

Merged
merged 1 commit into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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