ENABLE_3DCONNEXION_DEVICES -> Automatic detection of plugging/unplugging 3Dconnexion devices

This commit is contained in:
Enrico Turri 2019-10-04 10:59:27 +02:00
parent 1d463fc23f
commit 5a94ac9499
2 changed files with 50 additions and 22 deletions

View file

@ -11,6 +11,7 @@
#include <wx/glcanvas.h> #include <wx/glcanvas.h>
#include <boost/nowide/convert.hpp> #include <boost/nowide/convert.hpp>
#include <boost/log/trivial.hpp>
#include "I18N.hpp" #include "I18N.hpp"
@ -110,12 +111,12 @@ void Mouse3DController::init()
// Initialize the hidapi library // Initialize the hidapi library
int res = hid_init(); int res = hid_init();
if (res != 0) if (res != 0)
{
BOOST_LOG_TRIVIAL(error) << "Unable to initialize hidapi library";
return; return;
}
m_initialized = true; m_initialized = true;
connect_device();
start();
} }
void Mouse3DController::shutdown() void Mouse3DController::shutdown()
@ -124,10 +125,6 @@ void Mouse3DController::shutdown()
return; return;
stop(); stop();
if (m_thread.joinable())
m_thread.join();
disconnect_device(); disconnect_device();
// Finalize the hidapi library // Finalize the hidapi library
@ -137,8 +134,24 @@ void Mouse3DController::shutdown()
bool Mouse3DController::apply(Camera& camera) bool Mouse3DController::apply(Camera& camera)
{ {
if (!m_initialized)
return false;
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
return m_state.apply(camera);
// check if the user unplugged the device
if (!m_running && is_device_connected())
{
disconnect_device();
// hides the settings dialog if the user re-plug the device
m_settings_dialog = false;
}
// check if the user plugged the device
if (connect_device())
start();
return is_device_connected() ? m_state.apply(camera) : false;
} }
void Mouse3DController::render_settings_dialog(unsigned int canvas_width, unsigned int canvas_height) const void Mouse3DController::render_settings_dialog(unsigned int canvas_width, unsigned int canvas_height) const
@ -180,15 +193,18 @@ void Mouse3DController::render_settings_dialog(unsigned int canvas_width, unsign
ImGui::PopStyleVar(); ImGui::PopStyleVar();
} }
void Mouse3DController::connect_device() bool Mouse3DController::connect_device()
{ {
if (m_device != nullptr) if (is_device_connected())
return; return false;
// Enumerates devices // Enumerates devices
hid_device_info* devices = hid_enumerate(0, 0); hid_device_info* devices = hid_enumerate(0, 0);
if (devices == nullptr) if (devices == nullptr)
return; {
BOOST_LOG_TRIVIAL(error) << "Unable to enumerate HID devices";
return false;
}
// Searches for 1st connected 3Dconnexion device // Searches for 1st connected 3Dconnexion device
unsigned short vendor_id = 0; unsigned short vendor_id = 0;
@ -231,7 +247,7 @@ void Mouse3DController::connect_device()
hid_free_enumeration(devices); hid_free_enumeration(devices);
if (vendor_id == 0) if (vendor_id == 0)
return; return false;
// Open the 3Dconnexion device using the VID, PID // Open the 3Dconnexion device using the VID, PID
m_device = hid_open(vendor_id, product_id, nullptr); m_device = hid_open(vendor_id, product_id, nullptr);
@ -242,7 +258,9 @@ void Mouse3DController::connect_device()
hid_get_product_string(m_device, product.data(), 1024); hid_get_product_string(m_device, product.data(), 1024);
m_device_str = boost::nowide::narrow(product.data()); m_device_str = boost::nowide::narrow(product.data());
// gets device parameters from the config, if present BOOST_LOG_TRIVIAL(info) << "Connected device: " << m_device_str;
// get device parameters from the config, if present
double translation = 1.0; double translation = 1.0;
float rotation = 1.0; float rotation = 1.0;
wxGetApp().app_config->get_mouse_device_translation_speed(m_device_str, translation); wxGetApp().app_config->get_mouse_device_translation_speed(m_device_str, translation);
@ -251,26 +269,35 @@ void Mouse3DController::connect_device()
m_state.set_translation_scale(State::DefaultTranslationScale * std::max(0.5, std::min(2.0, translation))); m_state.set_translation_scale(State::DefaultTranslationScale * std::max(0.5, std::min(2.0, translation)));
m_state.set_rotation_scale(State::DefaultRotationScale * std::max(0.5f, std::min(2.0f, rotation))); m_state.set_rotation_scale(State::DefaultRotationScale * std::max(0.5f, std::min(2.0f, rotation)));
} }
return (m_device != nullptr);
} }
void Mouse3DController::disconnect_device() void Mouse3DController::disconnect_device()
{ {
if (m_device == nullptr) if (!is_device_connected())
return; return;
// stores current device parameters into the config // Stop the secondary thread, if running
if (m_thread.joinable())
m_thread.join();
// Store current device parameters into the config
wxGetApp().app_config->set_mouse_device(m_device_str, m_state.get_translation_scale() / State::DefaultTranslationScale, m_state.get_rotation_scale() / State::DefaultRotationScale); wxGetApp().app_config->set_mouse_device(m_device_str, m_state.get_translation_scale() / State::DefaultTranslationScale, m_state.get_rotation_scale() / State::DefaultRotationScale);
wxGetApp().app_config->save(); wxGetApp().app_config->save();
// Close the 3Dconnexion device // Close the 3Dconnexion device
hid_close(m_device); hid_close(m_device);
m_device = nullptr; m_device = nullptr;
BOOST_LOG_TRIVIAL(info) << "Disconnected device: " << m_device_str;
m_device_str = ""; m_device_str = "";
} }
void Mouse3DController::start() void Mouse3DController::start()
{ {
if ((m_device == nullptr) || m_running) if (!is_device_connected() || m_running)
return; return;
m_thread = std::thread(&Mouse3DController::run, this); m_thread = std::thread(&Mouse3DController::run, this);

View file

@ -72,23 +72,24 @@ public:
bool is_device_connected() const { return m_device != nullptr; } bool is_device_connected() const { return m_device != nullptr; }
bool is_running() const { return m_running; } bool is_running() const { return m_running; }
bool has_translation() const { return m_state.has_translation(); } // bool has_translation() const { return m_state.has_translation(); }
bool has_rotation() const { return m_state.has_rotation(); } // bool has_rotation() const { return m_state.has_rotation(); }
bool has_translation_or_rotation() const { return m_state.has_translation_or_rotation(); } bool has_translation_or_rotation() const { return m_state.has_translation_or_rotation(); }
bool has_any_button() const { return m_state.has_any_button(); } // bool has_any_button() const { return m_state.has_any_button(); }
bool apply(Camera& camera); bool apply(Camera& camera);
bool is_settings_dialog_shown() const { return m_settings_dialog; } bool is_settings_dialog_shown() const { return m_settings_dialog; }
void show_settings_dialog(bool show) { m_settings_dialog = show; } void show_settings_dialog(bool show) { m_settings_dialog = show && is_running(); }
void render_settings_dialog(unsigned int canvas_width, unsigned int canvas_height) const; void render_settings_dialog(unsigned int canvas_width, unsigned int canvas_height) const;
private: private:
void connect_device(); bool connect_device();
void disconnect_device(); void disconnect_device();
void start(); void start();
void stop() { m_running = false; } void stop() { m_running = false; }
// secondary thread methods
void run(); void run();
void collect_input(); void collect_input();
}; };