Welcome to mirror list, hosted at ThFree Co, Russian Federation.

Mouse3DHandlerMac.mm « GUI « slic3r « src - github.com/supermerill/SuperSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: b2d07a4e0b6f9c50e56337b0addef4f3ef477551 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#include "Mouse3DController.hpp"

#include <stdint.h>
#include <dlfcn.h>

#include <array>

#include <boost/log/trivial.hpp>
#include <cstdio>


static Slic3r::GUI::Mouse3DController* mouse_3d_controller = nullptr;

static uint16_t clientID = 0;

static bool driver_loaded = false;
static bool has_new_driver = false;  // drivers >= 10.2.2 are "new", and can process events on a separate thread

// replicate just enough of the 3Dx API for our uses, not everything the driver provides

#define kConnexionClientModeTakeOver 1
#define kConnexionMaskAxis 0x3f00
#define kConnexionMaskAll 0x3fff
#define kConnexionMaskAllButtons 0xffffffff
#define kConnexionCmdHandleButtons 2
#define kConnexionCmdHandleAxis 3
#define kConnexionCmdAppSpecific 10
#define kConnexionMsgDeviceState '3dSR'
#define kConnexionCtlGetDeviceID '3did'

#pragma pack(push, 2)
struct ConnexionDeviceState {
  uint16_t version;
  uint16_t client;
  uint16_t command;
  int16_t param;
  int32_t value;
  uint64_t time;
  uint8_t report[8];
  uint16_t buttons8;  // obsolete! (pre-10.x drivers)
  int16_t axis[6];    // tx, ty, tz, rx, ry, rz
  uint16_t address;
  uint32_t buttons;
};
#pragma pack(pop)

// callback functions:
typedef void (*AddedHandler)(uint32_t);
typedef void (*RemovedHandler)(uint32_t);
typedef void (*MessageHandler)(uint32_t, uint32_t msg_type, void *msg_arg);

// driver functions:
typedef int16_t (*SetConnexionHandlers_ptr)(MessageHandler, AddedHandler, RemovedHandler, bool);
typedef int16_t (*InstallConnexionHandlers_ptr)(MessageHandler, AddedHandler, RemovedHandler);
typedef void (*CleanupConnexionHandlers_ptr)();
typedef uint16_t (*RegisterConnexionClient_ptr)(uint32_t signature,
                                                const char *name,
                                                uint16_t mode,
                                                uint32_t mask);
typedef void (*SetConnexionClientButtonMask_ptr)(uint16_t clientID, uint32_t buttonMask);
typedef void (*UnregisterConnexionClient_ptr)(uint16_t clientID);
typedef int16_t (*ConnexionClientControl_ptr)(uint16_t clientID,
                                              uint32_t message,
                                              int32_t param,
                                              int32_t *result);

#define DECLARE_FUNC(name) name##_ptr name = nullptr

DECLARE_FUNC(SetConnexionHandlers);
DECLARE_FUNC(InstallConnexionHandlers);
DECLARE_FUNC(CleanupConnexionHandlers);
DECLARE_FUNC(RegisterConnexionClient);
DECLARE_FUNC(SetConnexionClientButtonMask);
DECLARE_FUNC(UnregisterConnexionClient);
DECLARE_FUNC(ConnexionClientControl);

static void *load_func(void *module, const char *func_name)
{
  void *func = dlsym(module, func_name);

  if (func) {
      BOOST_LOG_TRIVIAL(info) << func_name <<" loaded";
  }
  else {
    BOOST_LOG_TRIVIAL(error) <<"loading 3dx drivers dlsym error: "<< dlerror();
  }

  return func;
}

#define LOAD_FUNC(name) name = (name##_ptr)load_func(module, #name)

static void *module;  // handle to the whole driver

static bool load_driver_functions()
{
  if (driver_loaded)
    return true;

  module = dlopen("/Library/Frameworks/3DconnexionClient.framework/3DconnexionClient",
                  RTLD_LAZY | RTLD_LOCAL);

  if (module) {
    BOOST_LOG_TRIVIAL(info) << "loading 3dx drivers";
    LOAD_FUNC(SetConnexionHandlers);

    if (SetConnexionHandlers != nullptr) {
      driver_loaded = true;
      has_new_driver = true;
    }
    else {
      BOOST_LOG_TRIVIAL(info) << "installing 3dx drivers";
      LOAD_FUNC(InstallConnexionHandlers);
      driver_loaded = (InstallConnexionHandlers != nullptr);
    }

    if (driver_loaded) {
      LOAD_FUNC(CleanupConnexionHandlers);
      LOAD_FUNC(RegisterConnexionClient);
      LOAD_FUNC(SetConnexionClientButtonMask);
      LOAD_FUNC(UnregisterConnexionClient);
      LOAD_FUNC(ConnexionClientControl);
    }
  }
  else {
    BOOST_LOG_TRIVIAL(error) << "3dx drivers module loading error: "<< dlerror() ;
  }

  BOOST_LOG_TRIVIAL(info) << "3dx drivers loaded: " << (driver_loaded ? (has_new_driver ? "YES, new" : "YES, old") : "NO");
  return driver_loaded;
}

static void unload_driver()
{
  dlclose(module);
}

static void DeviceAdded(uint32_t unused)
{
  BOOST_LOG_TRIVIAL(info)<<"3dx device added";
  // determine exactly which device is plugged in
  int32_t result;
  ConnexionClientControl(clientID, kConnexionCtlGetDeviceID, 0, &result);
  int vendorID  = result >> 16;
  int productID = result & 0xffff;
  //TODO: verify device
  char buf[64];
  sprintf(buf, "VID%04X,PID%04X", vendorID, productID);
  mouse_3d_controller->connected(buf);
}

static void DeviceRemoved(uint32_t unused)
{
  BOOST_LOG_TRIVIAL(info) << "3dx device removed\n";
// not accessible in a free function
//  assert(m_connected);
//  assert(! m_device_str.empty());
  mouse_3d_controller->disconnected();
}

static void DeviceEvent(uint32_t unused, uint32_t msg_type, void *msg_arg)
{
  if (msg_type == kConnexionMsgDeviceState) {
    ConnexionDeviceState *s = (ConnexionDeviceState *)msg_arg;
    if (s->client == clientID) {
      switch (s->command) {
        case kConnexionCmdHandleAxis: {
          // The axis field is an array of 6 signed 16-bit integers corresponding to the 6 device axes. Data is ordered as Tx, Tz, Ty, Rx, Rz, Ry. The values reported are scaled by the driver according to the speed slider settings on the 3Dconnexion preference panel. At maximum speed, the range is - 1024 to 1024. Typical range that you should optimize your application for should be -500 to 500.
          // Actually we are getting values way over 1024. Max is probably 2048 now.
          Slic3r::GUI::Mouse3DController::DataPacketAxis packet;
          for (int i = 0; i < 6; ++ i)
              packet[i] = (double)s->axis[i]/350.0;//wanted to divide by 500 but 350 is used at raw input so i used same value.
          mouse_3d_controller->handle_input(packet);
          break;
        }
        case kConnexionCmdHandleButtons:
          break;
        case kConnexionCmdAppSpecific:
          break;
        default:
        break;
      }
    }
  }
}

namespace Slic3r {
namespace GUI {

// Initialize the application.
void Mouse3DController::init()
{
  BOOST_LOG_TRIVIAL(info) << "3dx mac handler starts";
  if (load_driver_functions()) {
    mouse_3d_controller = this;

    uint16_t error = has_new_driver ? 
      SetConnexionHandlers(DeviceEvent, DeviceAdded, DeviceRemoved, false) :
      InstallConnexionHandlers(DeviceEvent, DeviceAdded, DeviceRemoved);

    if (! error) {
      // Registration is done either by 4letter constant (CFBundleSignature - obsolete
      //and we dont have that) or Executable name in pascal string(first byte is string lenght).
      //If no packets are recieved the name might be different - check cmake. If debugging try commenting
      // set_target_properties(PrusaSlicer PROPERTIES OUTPUT_NAME "prusa-slicer")
      clientID = RegisterConnexionClient(
          0, "\013PrusaSlicer", kConnexionClientModeTakeOver, kConnexionMaskAxis);
        BOOST_LOG_TRIVIAL(info) << "3dx mac handler registered";
    }
  }
}

void Mouse3DController::shutdown()
{
  if (driver_loaded) {
    UnregisterConnexionClient(clientID);
    CleanupConnexionHandlers();
    unload_driver();
  }
  // Copy the current parameters to parameter database, mark the device as disconnected.
  this->disconnected();
  mouse_3d_controller = nullptr;
}

}}//namespace Slic3r::GUI