Bemanitools v5.26 release
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
exes += config
|
||||
rc_config := config.rc
|
||||
cppflags_config := -DUNICODE
|
||||
|
||||
libs_config := \
|
||||
eamio \
|
||||
geninput \
|
||||
util \
|
||||
|
||||
ldflags_config := \
|
||||
-lcomctl32 \
|
||||
-lcomdlg32 \
|
||||
-lgdi32 \
|
||||
-mwindows \
|
||||
|
||||
src_config := \
|
||||
analogs.c \
|
||||
bind-adv.c \
|
||||
bind.c \
|
||||
bind-light.c \
|
||||
buttons.c \
|
||||
eam.c \
|
||||
gametype.c \
|
||||
lights.c \
|
||||
main.c \
|
||||
schema.c \
|
||||
snap.c \
|
||||
spinner.c \
|
||||
usages.c \
|
||||
|
||||
@@ -0,0 +1,540 @@
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config/resource.h"
|
||||
#include "config/schema.h"
|
||||
#include "config/usages.h"
|
||||
|
||||
#include "geninput/hid-mgr.h"
|
||||
#include "geninput/input-config.h"
|
||||
#include "geninput/mapper.h"
|
||||
|
||||
#include "util/array.h"
|
||||
#include "util/defs.h"
|
||||
#include "util/log.h"
|
||||
#include "util/mem.h"
|
||||
#include "util/str.h"
|
||||
|
||||
#define SENSITIVITY_SCALE 4
|
||||
|
||||
struct analogs_ui {
|
||||
struct array children;
|
||||
};
|
||||
|
||||
struct analog_ui {
|
||||
const struct analog_def *def;
|
||||
struct array hids;
|
||||
struct array control_nos;
|
||||
struct hid_stub *selected_hid;
|
||||
uint8_t pos;
|
||||
};
|
||||
|
||||
static INT_PTR CALLBACK analogs_ui_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
static INT_PTR analogs_ui_handle_init(HWND hwnd, const PROPSHEETPAGE *psp);
|
||||
static INT_PTR analogs_ui_handle_activate(HWND hwnd);
|
||||
static INT_PTR analogs_ui_handle_passivate(HWND hwnd);
|
||||
static INT_PTR analogs_ui_handle_tick(HWND hwnd);
|
||||
static INT_PTR analogs_ui_handle_fini(HWND hwnd);
|
||||
|
||||
static INT_PTR CALLBACK analog_ui_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
static INT_PTR analog_ui_handle_init(HWND hwnd, struct analog_def *def);
|
||||
static void analog_ui_handle_init_label(HWND hwnd);
|
||||
static void analog_ui_handle_init_dev(HWND hwnd);
|
||||
static void analog_ui_handle_init_sensitivity(HWND hwnd);
|
||||
static bool analog_ui_match_device(struct hid_stub *hid);
|
||||
static void analog_ui_populate_controls(HWND hwnd);
|
||||
static INT_PTR analog_ui_handle_device_change(HWND hwnd);
|
||||
static INT_PTR analog_ui_handle_control_change(HWND hwnd);
|
||||
static INT_PTR analog_ui_handle_sensitivity_change(HWND hwnd);
|
||||
static INT_PTR analog_ui_handle_tick(HWND hwnd);
|
||||
static INT_PTR analog_ui_handle_fini(HWND hwnd);
|
||||
|
||||
HPROPSHEETPAGE analogs_ui_tab_create(HINSTANCE inst,
|
||||
const struct schema *schema)
|
||||
{
|
||||
PROPSHEETPAGE psp;
|
||||
|
||||
memset(&psp, 0, sizeof(psp));
|
||||
psp.dwSize = sizeof(psp);
|
||||
psp.dwFlags = PSP_DEFAULT;
|
||||
psp.hInstance = inst;
|
||||
psp.pszTemplate = MAKEINTRESOURCE(IDD_TAB_ANALOGS);
|
||||
psp.pfnDlgProc = analogs_ui_dlg_proc;
|
||||
psp.lParam = (LPARAM) schema;
|
||||
|
||||
return CreatePropertySheetPage(&psp);
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK analogs_ui_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam)
|
||||
{
|
||||
const NMHDR *n;
|
||||
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
return analogs_ui_handle_init(hwnd, (PROPSHEETPAGE *) lparam);
|
||||
|
||||
case WM_NOTIFY:
|
||||
n = (NMHDR *) lparam;
|
||||
|
||||
switch (n->code) {
|
||||
case PSN_SETACTIVE:
|
||||
return analogs_ui_handle_activate(hwnd);
|
||||
|
||||
case PSN_KILLACTIVE:
|
||||
return analogs_ui_handle_passivate(hwnd);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
case WM_TIMER:
|
||||
return analogs_ui_handle_tick(hwnd);
|
||||
|
||||
case WM_DESTROY:
|
||||
return analogs_ui_handle_fini(hwnd);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static INT_PTR analogs_ui_handle_init(HWND hwnd, const PROPSHEETPAGE *psp)
|
||||
{
|
||||
struct analogs_ui *ui;
|
||||
const struct schema *schema;
|
||||
long ypos;
|
||||
size_t i;
|
||||
HINSTANCE inst;
|
||||
HWND child;
|
||||
RECT r;
|
||||
|
||||
ui = xmalloc(sizeof(*ui));
|
||||
array_init(&ui->children);
|
||||
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM) ui);
|
||||
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
schema = (struct schema *) psp->lParam;
|
||||
|
||||
ypos = 0;
|
||||
|
||||
for (i = 0 ; i < schema->nanalogs ; i++) {
|
||||
child = CreateDialogParam(inst, MAKEINTRESOURCE(IDD_ANALOG), hwnd,
|
||||
analog_ui_dlg_proc, (LPARAM) &schema->analogs[i]);
|
||||
|
||||
GetWindowRect(child, &r);
|
||||
SetWindowPos(child, HWND_BOTTOM, 0, ypos, 0, 0,
|
||||
SWP_NOSIZE | SWP_SHOWWINDOW);
|
||||
|
||||
ypos += r.bottom - r.top;
|
||||
|
||||
*array_append(HWND, &ui->children) = child;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR analogs_ui_handle_activate(HWND hwnd)
|
||||
{
|
||||
SetTimer(hwnd, 1, 17, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR analogs_ui_handle_passivate(HWND hwnd)
|
||||
{
|
||||
KillTimer(hwnd, 1);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR analogs_ui_handle_tick(HWND hwnd)
|
||||
{
|
||||
HWND child;
|
||||
struct analogs_ui *ui;
|
||||
size_t i;
|
||||
|
||||
mapper_update();
|
||||
|
||||
ui = (struct analogs_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
for (i = 0 ; i < ui->children.nitems ; i++) {
|
||||
child = *array_item(HWND, &ui->children, i);
|
||||
SendMessage(child, WM_USER, 0, 0);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR analogs_ui_handle_fini(HWND hwnd)
|
||||
{
|
||||
struct analogs_ui *ui;
|
||||
|
||||
ui = (struct analogs_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
array_fini(&ui->children);
|
||||
free(ui);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK analog_ui_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
return analog_ui_handle_init(hwnd, (struct analog_def *) lparam);
|
||||
|
||||
case WM_USER:
|
||||
return analog_ui_handle_tick(hwnd);
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (HIWORD(wparam)) {
|
||||
case CBN_SELCHANGE:
|
||||
switch (LOWORD(wparam)) {
|
||||
case IDC_DEVICE:
|
||||
return analog_ui_handle_device_change(hwnd);
|
||||
|
||||
case IDC_CONTROL:
|
||||
return analog_ui_handle_control_change(hwnd);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
case WM_HSCROLL:
|
||||
if (GetDlgItem(hwnd, IDC_SENSITIVITY) == (HWND) lparam) {
|
||||
return analog_ui_handle_sensitivity_change(hwnd);
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
case WM_DESTROY:
|
||||
return analog_ui_handle_fini(hwnd);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR analog_ui_handle_init(HWND hwnd, struct analog_def *def)
|
||||
{
|
||||
struct analog_ui *ui;
|
||||
|
||||
ui = xmalloc(sizeof(*ui));
|
||||
ui->def = def;
|
||||
array_init(&ui->hids);
|
||||
array_init(&ui->control_nos);
|
||||
ui->selected_hid = NULL;
|
||||
ui->pos = 0;
|
||||
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM) ui);
|
||||
|
||||
analog_ui_handle_init_label(hwnd);
|
||||
analog_ui_handle_init_dev(hwnd);
|
||||
analog_ui_handle_init_sensitivity(hwnd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void analog_ui_handle_init_label(HWND hwnd)
|
||||
{
|
||||
struct analog_ui *ui;
|
||||
wchar_t label[128];
|
||||
HINSTANCE inst;
|
||||
HWND box;
|
||||
|
||||
ui = (struct analog_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
box = GetDlgItem(hwnd, IDC_GROUP);
|
||||
|
||||
LoadString(inst, ui->def->label_rsrc, label, lengthof(label));
|
||||
SendMessage(box, WM_SETTEXT, 0, (LPARAM) label);
|
||||
}
|
||||
|
||||
static void analog_ui_handle_init_dev(HWND hwnd)
|
||||
{
|
||||
struct analog_ui *ui;
|
||||
struct mapped_analog ma;
|
||||
wchar_t *dev_name;
|
||||
struct hid_stub *hid;
|
||||
size_t nchars;
|
||||
LRESULT index;
|
||||
HWND dev_list;
|
||||
|
||||
ui = (struct analog_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
dev_list = GetDlgItem(hwnd, IDC_DEVICE);
|
||||
|
||||
SendMessage(dev_list, CB_ADDSTRING, 0, (LPARAM) L"");
|
||||
|
||||
hid_mgr_lock();
|
||||
|
||||
ma.hid = NULL;
|
||||
mapper_get_analog_map(ui->def->tag, &ma);
|
||||
|
||||
for (hid = hid_mgr_get_first_stub()
|
||||
; hid != NULL
|
||||
; hid = hid_mgr_get_next_stub(hid)) {
|
||||
if (!analog_ui_match_device(hid)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hid_stub_get_name(hid, NULL, &nchars)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dev_name = xmalloc(nchars * sizeof(*dev_name));
|
||||
|
||||
if (!hid_stub_get_name(hid, dev_name, &nchars)) {
|
||||
free(dev_name);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
index = SendMessage(dev_list, CB_ADDSTRING, 0, (LPARAM) dev_name);
|
||||
|
||||
free(dev_name);
|
||||
|
||||
*array_append(struct hid_stub *, &ui->hids) = hid;
|
||||
|
||||
if (ma.hid == hid) {
|
||||
SendMessage(dev_list, CB_SETCURSEL, index, 0);
|
||||
|
||||
ui->selected_hid = hid;
|
||||
analog_ui_populate_controls(hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
hid_mgr_unlock();
|
||||
}
|
||||
|
||||
static void analog_ui_handle_init_sensitivity(HWND hwnd)
|
||||
{
|
||||
struct analog_ui *ui;
|
||||
int pos;
|
||||
HWND slider;
|
||||
|
||||
ui = (struct analog_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
slider = GetDlgItem(hwnd, IDC_SENSITIVITY);
|
||||
pos = 256 * SENSITIVITY_SCALE + mapper_get_analog_sensitivity(ui->def->tag);
|
||||
|
||||
SendMessage(slider, TBM_SETTICFREQ, 256, 0);
|
||||
SendMessage(slider, TBM_SETRANGE, FALSE,
|
||||
MAKELPARAM(0, SENSITIVITY_SCALE * 256 * 2));
|
||||
SendMessage(slider, TBM_SETPOS, TRUE, (LPARAM) pos);
|
||||
|
||||
EnableWindow(slider, !mapper_is_analog_absolute(ui->def->tag));
|
||||
}
|
||||
|
||||
static bool analog_ui_match_device(struct hid_stub *hid)
|
||||
{
|
||||
struct hid_control *controls;
|
||||
size_t ncontrols;
|
||||
size_t i;
|
||||
|
||||
if (!hid_stub_get_controls(hid, NULL, &ncontrols)) {
|
||||
goto size_fail;
|
||||
}
|
||||
|
||||
controls = xmalloc(ncontrols * sizeof(*controls));
|
||||
|
||||
if (!hid_stub_get_controls(hid, controls, &ncontrols)) {
|
||||
goto content_fail;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < ncontrols ; i++) {
|
||||
if (controls[i].value_max - controls[i].value_min > 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(controls);
|
||||
|
||||
return i < ncontrols;
|
||||
|
||||
content_fail:
|
||||
free(controls);
|
||||
|
||||
size_fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static void analog_ui_populate_controls(HWND hwnd)
|
||||
{
|
||||
char usage_desc[512];
|
||||
wchar_t *tmp;
|
||||
struct analog_ui *ui;
|
||||
struct mapped_analog ma;
|
||||
struct hid_control *controls;
|
||||
size_t ncontrols;
|
||||
size_t i;
|
||||
long nitems;
|
||||
LRESULT index;
|
||||
HWND controls_ctl;
|
||||
|
||||
ui = (struct analog_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
controls_ctl = GetDlgItem(hwnd, IDC_CONTROL);
|
||||
nitems = (long) SendMessage(controls_ctl, CB_GETCOUNT, 0, 0);
|
||||
|
||||
InvalidateRect(controls_ctl, NULL, TRUE);
|
||||
|
||||
for (index = nitems ; index >= 0 ; index--) {
|
||||
SendMessage(controls_ctl, CB_DELETESTRING, index, 0);
|
||||
}
|
||||
|
||||
array_fini(&ui->control_nos);
|
||||
array_init(&ui->control_nos);
|
||||
|
||||
if (ui->selected_hid == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hid_stub_get_controls(ui->selected_hid, NULL, &ncontrols)) {
|
||||
goto size_fail;
|
||||
}
|
||||
|
||||
controls = xmalloc(sizeof(*controls) * ncontrols);
|
||||
|
||||
if (!hid_stub_get_controls(ui->selected_hid, controls, &ncontrols)) {
|
||||
goto content_fail;
|
||||
}
|
||||
|
||||
SendMessage(controls_ctl, CB_ADDSTRING, 0, (LPARAM) L"");
|
||||
|
||||
mapper_get_analog_map(ui->def->tag, &ma);
|
||||
|
||||
for (i = 0 ; i < ncontrols ; i++) {
|
||||
if (controls[i].value_max - controls[i].value_min <= 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
usages_get(usage_desc, lengthof(usage_desc), controls[i].usage);
|
||||
tmp = str_widen(usage_desc);
|
||||
|
||||
index = SendMessage(controls_ctl, CB_ADDSTRING, 0, (LPARAM) tmp);
|
||||
free(tmp);
|
||||
|
||||
if (i == ma.control_no) {
|
||||
SendMessage(controls_ctl, CB_SETCURSEL, index, 0);
|
||||
}
|
||||
|
||||
*array_append(size_t, &ui->control_nos) = i;
|
||||
}
|
||||
|
||||
free(controls);
|
||||
|
||||
return;
|
||||
|
||||
content_fail:
|
||||
free(controls);
|
||||
|
||||
size_fail:
|
||||
return;
|
||||
}
|
||||
|
||||
static INT_PTR analog_ui_handle_device_change(HWND hwnd)
|
||||
{
|
||||
struct mapped_analog ma;
|
||||
struct analog_ui *ui;
|
||||
LRESULT index;
|
||||
|
||||
ui = (struct analog_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
index = SendMessage(GetDlgItem(hwnd, IDC_DEVICE), CB_GETCURSEL, 0, 0);
|
||||
|
||||
log_assert((size_t) index <= ui->hids.nitems);
|
||||
|
||||
if (index == 0) {
|
||||
ui->selected_hid = NULL;
|
||||
} else {
|
||||
ui->selected_hid = *array_item(struct hid_stub *, &ui->hids, index - 1);
|
||||
}
|
||||
|
||||
ma.hid = NULL;
|
||||
mapper_set_analog_map(ui->def->tag, &ma);
|
||||
|
||||
hid_mgr_lock();
|
||||
analog_ui_populate_controls(hwnd);
|
||||
hid_mgr_unlock();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR analog_ui_handle_control_change(HWND hwnd)
|
||||
{
|
||||
struct mapped_analog ma;
|
||||
struct analog_ui *ui;
|
||||
LRESULT index;
|
||||
HWND slider;
|
||||
|
||||
ui = (struct analog_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
index = SendMessage(GetDlgItem(hwnd, IDC_CONTROL), CB_GETCURSEL, 0, 0);
|
||||
|
||||
log_assert((size_t) index <= ui->control_nos.nitems);
|
||||
|
||||
if (index == 0) {
|
||||
ma.hid = NULL;
|
||||
} else {
|
||||
ma.hid = ui->selected_hid;
|
||||
ma.control_no = *array_item(size_t, &ui->control_nos, index - 1);
|
||||
}
|
||||
|
||||
mapper_set_analog_map(ui->def->tag, &ma);
|
||||
|
||||
slider = GetDlgItem(hwnd, IDC_SENSITIVITY);
|
||||
|
||||
EnableWindow(slider, !mapper_is_analog_absolute(ui->def->tag));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR analog_ui_handle_sensitivity_change(HWND hwnd)
|
||||
{
|
||||
struct analog_ui *ui;
|
||||
int pos;
|
||||
HWND slider;
|
||||
|
||||
ui = (struct analog_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
slider = GetDlgItem(hwnd, IDC_SENSITIVITY);
|
||||
pos = (int) SendMessage(slider, TBM_GETPOS, 0, 0);
|
||||
|
||||
mapper_set_analog_sensitivity(ui->def->tag, pos - 256 * SENSITIVITY_SCALE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR analog_ui_handle_tick(HWND hwnd)
|
||||
{
|
||||
struct analog_ui *ui;
|
||||
HWND pos_ctl;
|
||||
|
||||
ui = (struct analog_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
pos_ctl = GetDlgItem(hwnd, IDC_POSITION);
|
||||
|
||||
ui->pos = mapper_read_analog(ui->def->tag);
|
||||
|
||||
SendMessage(pos_ctl, WM_USER, 0, (LPARAM) ui->pos);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR analog_ui_handle_fini(HWND hwnd)
|
||||
{
|
||||
struct analog_ui *ui;
|
||||
|
||||
ui = (struct analog_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
array_fini(&ui->hids);
|
||||
array_fini(&ui->control_nos);
|
||||
free(ui);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,530 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config/bind-adv.h"
|
||||
#include "config/resource.h"
|
||||
#include "config/usages.h"
|
||||
|
||||
#include "geninput/hid-mgr.h"
|
||||
|
||||
#include "util/array.h"
|
||||
#include "util/defs.h"
|
||||
#include "util/mem.h"
|
||||
#include "util/str.h"
|
||||
|
||||
struct bind_adv_state {
|
||||
uintptr_t timer_id;
|
||||
struct mapped_action ma;
|
||||
struct array devs;
|
||||
struct hid_stub *cur_hid;
|
||||
struct hid_control *ctls;
|
||||
size_t nctls;
|
||||
bool was_valid;
|
||||
};
|
||||
|
||||
static INT_PTR CALLBACK bind_adv_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
static INT_PTR bind_adv_handle_init(HWND hwnd, struct bind_adv_state *state);
|
||||
static void bind_adv_handle_init_devs(HWND hwnd);
|
||||
static void bind_adv_handle_init_insert_dev(HWND hwnd, struct hid_stub *hid);
|
||||
static INT_PTR bind_adv_handle_change_ctl(HWND hwnd);
|
||||
static INT_PTR bind_adv_handle_change_dev(HWND hwnd);
|
||||
static INT_PTR bind_adv_handle_change_range(HWND hwnd);
|
||||
static INT_PTR bind_adv_handle_tick(HWND hwnd);
|
||||
static INT_PTR bind_adv_handle_ok(HWND hwnd);
|
||||
static INT_PTR bind_adv_handle_fini(HWND hwnd);
|
||||
static bool bind_adv_get_dev_no(HWND hwnd, size_t *dev_no_out);
|
||||
static bool bind_adv_get_ctl_no(HWND hwnd, size_t *ctl_no_out);
|
||||
static bool bind_adv_get_range(HWND hwnd, int32_t *out_min, int32_t *out_max);
|
||||
static bool bind_adv_get_int(HWND control, int32_t *out);
|
||||
static bool bind_adv_is_valid(HWND hwnd);
|
||||
static void bind_adv_validate(HWND hwnd);
|
||||
static void bind_adv_select_dev(HWND hwnd, size_t dev_no);
|
||||
static void bind_adv_select_ctl(HWND hwnd, size_t ctl_no);
|
||||
static void bind_adv_set_range(HWND hwnd, int32_t range_min, int32_t range_max);
|
||||
|
||||
bool bind_adv(HINSTANCE inst, HWND hwnd, struct mapped_action *ma,
|
||||
bool was_valid)
|
||||
{
|
||||
struct bind_adv_state state;
|
||||
INT_PTR ok;
|
||||
|
||||
memset(&state, 0, sizeof(state));
|
||||
|
||||
state.ma = *ma;
|
||||
state.was_valid = was_valid;
|
||||
|
||||
ok = DialogBoxParam(inst, MAKEINTRESOURCE(IDD_BIND_ADV), hwnd,
|
||||
bind_adv_dlg_proc, (LPARAM) &state) != 0;
|
||||
|
||||
if (ok) {
|
||||
*ma = state.ma;
|
||||
}
|
||||
|
||||
return ok != 0;
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK bind_adv_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
return bind_adv_handle_init(hwnd, (struct bind_adv_state *) lparam);
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wparam)) {
|
||||
case IDC_CONTROL:
|
||||
switch (HIWORD(wparam)) {
|
||||
case CBN_SELCHANGE:
|
||||
return bind_adv_handle_change_ctl(hwnd);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
case IDC_DEVICE:
|
||||
switch (HIWORD(wparam)) {
|
||||
case CBN_SELCHANGE:
|
||||
return bind_adv_handle_change_dev(hwnd);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
case IDC_BINDING_MIN:
|
||||
case IDC_BINDING_MAX:
|
||||
switch (HIWORD(wparam)) {
|
||||
case EN_CHANGE:
|
||||
return bind_adv_handle_change_range(hwnd);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
case IDOK:
|
||||
switch (HIWORD(wparam)) {
|
||||
case BN_CLICKED:
|
||||
return bind_adv_handle_ok(hwnd);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
case IDCANCEL:
|
||||
switch (HIWORD(wparam)) {
|
||||
case BN_CLICKED:
|
||||
EndDialog(hwnd, FALSE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
case WM_TIMER:
|
||||
return bind_adv_handle_tick(hwnd);
|
||||
|
||||
case WM_DESTROY:
|
||||
return bind_adv_handle_fini(hwnd);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static INT_PTR bind_adv_handle_init(HWND hwnd, struct bind_adv_state *state)
|
||||
{
|
||||
struct hid_stub *hid;
|
||||
size_t i;
|
||||
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM) state);
|
||||
|
||||
bind_adv_handle_init_devs(hwnd);
|
||||
|
||||
state->timer_id = SetTimer(hwnd, 1, 17, NULL);
|
||||
|
||||
if (!state->was_valid) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < state->devs.nitems ; i++) {
|
||||
hid = *array_item(struct hid_stub *, &state->devs, i);
|
||||
|
||||
if (hid == state->ma.hid) {
|
||||
bind_adv_select_dev(hwnd, (int) i);
|
||||
bind_adv_select_ctl(hwnd, state->ma.control_no);
|
||||
bind_adv_set_range(hwnd, state->ma.value_min,
|
||||
state->ma.value_max);
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void bind_adv_handle_init_devs(HWND hwnd)
|
||||
{
|
||||
struct hid_stub *hid;
|
||||
|
||||
hid_mgr_lock();
|
||||
|
||||
for (hid = hid_mgr_get_first_stub()
|
||||
; hid != NULL
|
||||
; hid = hid_mgr_get_next_stub(hid)) {
|
||||
bind_adv_handle_init_insert_dev(hwnd, hid);
|
||||
}
|
||||
|
||||
hid_mgr_unlock();
|
||||
}
|
||||
|
||||
static void bind_adv_handle_init_insert_dev(HWND hwnd, struct hid_stub *hid)
|
||||
{
|
||||
struct bind_adv_state *state;
|
||||
wchar_t *name;
|
||||
size_t nchars;
|
||||
HWND devs;
|
||||
|
||||
state = (struct bind_adv_state *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
devs = GetDlgItem(hwnd, IDC_DEVICE);
|
||||
|
||||
if (!hid_stub_get_name(hid, NULL, &nchars)) {
|
||||
goto size_fail;
|
||||
}
|
||||
|
||||
name = xmalloc(sizeof(*name) * nchars);
|
||||
|
||||
if (!hid_stub_get_name(hid, name, &nchars)) {
|
||||
goto name_fail;
|
||||
}
|
||||
|
||||
*array_append(struct hid_stub *, &state->devs) = hid;
|
||||
|
||||
SendMessage(devs, CB_ADDSTRING, 0, (LPARAM) name);
|
||||
|
||||
name_fail:
|
||||
free(name);
|
||||
|
||||
size_fail:
|
||||
;
|
||||
}
|
||||
|
||||
static INT_PTR bind_adv_handle_change_ctl(HWND hwnd)
|
||||
{
|
||||
size_t ctl_no;
|
||||
|
||||
if (bind_adv_get_ctl_no(hwnd, &ctl_no)) {
|
||||
bind_adv_select_ctl(hwnd, ctl_no);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR bind_adv_handle_change_dev(HWND hwnd)
|
||||
{
|
||||
size_t dev_no;
|
||||
|
||||
if (bind_adv_get_dev_no(hwnd, &dev_no)) {
|
||||
bind_adv_select_dev(hwnd, dev_no);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR bind_adv_handle_change_range(HWND hwnd)
|
||||
{
|
||||
bind_adv_validate(hwnd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR bind_adv_handle_tick(HWND hwnd)
|
||||
{
|
||||
struct bind_adv_state *state;
|
||||
wchar_t wchars[16];
|
||||
size_t ctl_no;
|
||||
int32_t value;
|
||||
HWND label;
|
||||
|
||||
state = (struct bind_adv_state *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
if (!bind_adv_get_ctl_no(hwnd, &ctl_no)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
hid_mgr_lock();
|
||||
|
||||
if (hid_stub_get_value(state->cur_hid, ctl_no, &value)) {
|
||||
wstr_format(wchars, lengthof(wchars), L"%d", value);
|
||||
|
||||
label = GetDlgItem(hwnd, IDC_CURRENT);
|
||||
SetWindowText(label, wchars);
|
||||
}
|
||||
|
||||
hid_mgr_unlock();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR bind_adv_handle_ok(HWND hwnd)
|
||||
{
|
||||
struct bind_adv_state *state;
|
||||
size_t dev_no;
|
||||
size_t ctl_no;
|
||||
|
||||
state = (struct bind_adv_state *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
/* bind_adv_validate() ought to ensure that OK is disabled whenever the
|
||||
user's input is somehow invalid. Still, it never hurts to double check.
|
||||
|
||||
Ignore any OK clicks that we somehow receive with invalid input. */
|
||||
|
||||
if (!bind_adv_get_dev_no(hwnd, &dev_no)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
state->ma.hid = *array_item(struct hid_stub *, &state->devs, dev_no);
|
||||
|
||||
if (!bind_adv_get_ctl_no(hwnd, &ctl_no)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
state->ma.control_no = ctl_no;
|
||||
|
||||
if (!bind_adv_get_range(hwnd, &state->ma.value_min, &state->ma.value_max)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Input OK, shut down this dialog. */
|
||||
|
||||
EndDialog(hwnd, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR bind_adv_handle_fini(HWND hwnd)
|
||||
{
|
||||
struct bind_adv_state *state;
|
||||
|
||||
state = (struct bind_adv_state *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
array_fini(&state->devs);
|
||||
|
||||
KillTimer(hwnd, state->timer_id);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static bool bind_adv_get_dev_no(HWND hwnd, size_t *dev_no_out)
|
||||
{
|
||||
const struct bind_adv_state *state;
|
||||
size_t dev_no;
|
||||
HWND devs;
|
||||
|
||||
state = (struct bind_adv_state *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
devs = GetDlgItem(hwnd, IDC_DEVICE);
|
||||
|
||||
dev_no = SendMessage(devs, CB_GETCURSEL, 0, 0);
|
||||
|
||||
if (dev_no >= state->devs.nitems) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dev_no_out != NULL) {
|
||||
*dev_no_out = dev_no;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bind_adv_get_ctl_no(HWND hwnd, size_t *ctl_no_out)
|
||||
{
|
||||
const struct bind_adv_state *state;
|
||||
size_t ctl_no;
|
||||
HWND ctls;
|
||||
|
||||
state = (struct bind_adv_state *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
ctls = GetDlgItem(hwnd, IDC_CONTROL);
|
||||
|
||||
ctl_no = SendMessage(ctls, CB_GETCURSEL, 0, 0);
|
||||
|
||||
if (ctl_no >= state->nctls) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ctl_no_out != NULL) {
|
||||
*ctl_no_out = ctl_no;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bind_adv_get_range(HWND hwnd, int32_t *out_min, int32_t *out_max)
|
||||
{
|
||||
HWND wnd_min;
|
||||
HWND wnd_max;
|
||||
|
||||
wnd_min = GetDlgItem(hwnd, IDC_BINDING_MIN);
|
||||
wnd_max = GetDlgItem(hwnd, IDC_BINDING_MAX);
|
||||
|
||||
return bind_adv_get_int(wnd_min, out_min)
|
||||
&& bind_adv_get_int(wnd_max, out_max);
|
||||
}
|
||||
|
||||
static bool bind_adv_get_int(HWND control, int32_t *out)
|
||||
{
|
||||
wchar_t text[16];
|
||||
int32_t tmp;
|
||||
|
||||
text[0] = L'\0';
|
||||
GetWindowText(control, text, lengthof(text));
|
||||
|
||||
if (swscanf(text, L"%d", &tmp) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (out != NULL) {
|
||||
*out = tmp;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bind_adv_is_valid(HWND hwnd)
|
||||
{
|
||||
if (!bind_adv_get_dev_no(hwnd, NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bind_adv_get_ctl_no(hwnd, NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!bind_adv_get_range(hwnd, NULL, NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void bind_adv_validate(HWND hwnd)
|
||||
{
|
||||
HWND ok;
|
||||
|
||||
ok = GetDlgItem(hwnd, IDOK);
|
||||
EnableWindow(ok, bind_adv_is_valid(hwnd) ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
static void bind_adv_select_dev(HWND hwnd, size_t dev_no)
|
||||
{
|
||||
struct bind_adv_state *state;
|
||||
struct hid_stub *hid;
|
||||
char chars[256];
|
||||
wchar_t wchars[256];
|
||||
size_t i;
|
||||
HWND ctls;
|
||||
HWND devs;
|
||||
|
||||
state = (struct bind_adv_state *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
ctls = GetDlgItem(hwnd, IDC_CONTROL);
|
||||
devs = GetDlgItem(hwnd, IDC_DEVICE);
|
||||
|
||||
if (dev_no >= state->devs.nitems) {
|
||||
return;
|
||||
}
|
||||
|
||||
SendMessage(devs, CB_SETCURSEL, (WPARAM) dev_no, 0);
|
||||
SendMessage(ctls, CB_RESETCONTENT, 0, 0);
|
||||
|
||||
hid = *array_item(struct hid_stub *, &state->devs, dev_no);
|
||||
|
||||
state->cur_hid = hid;
|
||||
|
||||
hid_mgr_lock();
|
||||
|
||||
if (!hid_stub_get_controls(state->cur_hid, NULL, &state->nctls)) {
|
||||
goto size_fail;
|
||||
}
|
||||
|
||||
free(state->ctls);
|
||||
state->ctls = xmalloc(sizeof(*state->ctls) * state->nctls);
|
||||
|
||||
if (!hid_stub_get_controls(state->cur_hid, state->ctls, &state->nctls)) {
|
||||
goto data_fail;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < state->nctls ; i++) {
|
||||
wchars[0] = L'\0';
|
||||
|
||||
usages_get(chars, lengthof(chars), state->ctls[i].usage);
|
||||
MultiByteToWideChar(CP_UTF8, 0, chars, -1, wchars, lengthof(wchars));
|
||||
|
||||
SendMessage(ctls, CB_ADDSTRING, 0, (LPARAM) wchars);
|
||||
}
|
||||
|
||||
hid_mgr_unlock();
|
||||
|
||||
bind_adv_validate(hwnd);
|
||||
|
||||
return;
|
||||
|
||||
data_fail:
|
||||
free(state->ctls);
|
||||
|
||||
state->ctls = NULL;
|
||||
state->nctls = 0;
|
||||
|
||||
size_fail:
|
||||
hid_mgr_unlock();
|
||||
|
||||
bind_adv_validate(hwnd);
|
||||
}
|
||||
|
||||
static void bind_adv_select_ctl(HWND hwnd, size_t ctl_no)
|
||||
{
|
||||
wchar_t text[128];
|
||||
struct bind_adv_state *state;
|
||||
const struct hid_control *ctl;
|
||||
HWND ctls;
|
||||
HWND limit_min;
|
||||
HWND limit_max;
|
||||
|
||||
state = (struct bind_adv_state *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
ctls = GetDlgItem(hwnd, IDC_CONTROL);
|
||||
limit_min = GetDlgItem(hwnd, IDC_LIMIT_MIN);
|
||||
limit_max = GetDlgItem(hwnd, IDC_LIMIT_MAX);
|
||||
|
||||
if (ctl_no >= state->nctls) {
|
||||
return;
|
||||
}
|
||||
|
||||
SendMessage(ctls, CB_SETCURSEL, (WPARAM) ctl_no, 0);
|
||||
|
||||
ctl = &state->ctls[ctl_no];
|
||||
|
||||
wstr_format(text, lengthof(text), L"%d", ctl->value_min);
|
||||
SetWindowText(limit_min, text);
|
||||
|
||||
wstr_format(text, lengthof(text), L"%d", ctl->value_max);
|
||||
SetWindowText(limit_max, text);
|
||||
|
||||
bind_adv_validate(hwnd);
|
||||
}
|
||||
|
||||
static void bind_adv_set_range(HWND hwnd, int32_t range_min, int32_t range_max)
|
||||
{
|
||||
wchar_t text[16];
|
||||
HWND wnd_min;
|
||||
HWND wnd_max;
|
||||
|
||||
wnd_min = GetDlgItem(hwnd, IDC_BINDING_MIN);
|
||||
wnd_max = GetDlgItem(hwnd, IDC_BINDING_MAX);
|
||||
|
||||
wstr_format(text, lengthof(text), L"%d", range_min);
|
||||
SetWindowText(wnd_min, text);
|
||||
|
||||
wstr_format(text, lengthof(text), L"%d", range_max);
|
||||
SetWindowText(wnd_max, text);
|
||||
|
||||
bind_adv_validate(hwnd);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef CONFIG_BIND_ADV_H
|
||||
#define CONFIG_BIND_ADV_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "config/schema.h"
|
||||
|
||||
#include "geninput/input-config.h"
|
||||
|
||||
bool bind_adv(HINSTANCE inst, HWND hwnd, struct mapped_action *ma,
|
||||
bool was_valid);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,162 @@
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config/resource.h"
|
||||
#include "config/schema.h"
|
||||
#include "config/usages.h"
|
||||
|
||||
#include "geninput/hid-mgr.h"
|
||||
#include "geninput/mapper.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/mem.h"
|
||||
|
||||
struct bind_light_state {
|
||||
const struct schema *schema;
|
||||
const struct mapped_light *ml;
|
||||
uint8_t *game_light;
|
||||
bool *bound;
|
||||
};
|
||||
|
||||
static INT_PTR CALLBACK bind_light_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
static INT_PTR bind_light_handle_init(HWND hwnd,
|
||||
struct bind_light_state *state);
|
||||
static INT_PTR bind_light_handle_ok(HWND hwnd);
|
||||
|
||||
bool bind_light(HINSTANCE inst, HWND hwnd, const struct schema *schema,
|
||||
const struct mapped_light *ml, uint8_t *game_light, bool *bound)
|
||||
{
|
||||
struct bind_light_state state;
|
||||
|
||||
state.schema = schema;
|
||||
state.ml = ml;
|
||||
state.game_light = game_light;
|
||||
state.bound = bound;
|
||||
|
||||
return DialogBoxParam(inst, MAKEINTRESOURCE(IDD_BIND_LIGHT), hwnd,
|
||||
bind_light_dlg_proc, (LPARAM) &state) != 0;
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK bind_light_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
return bind_light_handle_init(hwnd,
|
||||
(struct bind_light_state *) lparam);
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wparam)) {
|
||||
case IDOK:
|
||||
switch (HIWORD(wparam)) {
|
||||
case BN_CLICKED:
|
||||
return bind_light_handle_ok(hwnd);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
case IDCANCEL:
|
||||
switch (HIWORD(wparam)) {
|
||||
case BN_CLICKED:
|
||||
EndDialog(hwnd, FALSE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static INT_PTR bind_light_handle_init(HWND hwnd,
|
||||
struct bind_light_state *state)
|
||||
{
|
||||
char chars[256];
|
||||
wchar_t wchars[256];
|
||||
struct hid_light *lights;
|
||||
size_t nlights;
|
||||
size_t i;
|
||||
HINSTANCE inst;
|
||||
HWND hid_light_ctl;
|
||||
HWND game_light_ctl;
|
||||
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (INT_PTR) state);
|
||||
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
game_light_ctl = GetDlgItem(hwnd, IDC_GAME_LIGHT);
|
||||
|
||||
ComboBox_AddString(game_light_ctl, L"");
|
||||
|
||||
for (i = 0 ; i < state->schema->nlights ; i++) {
|
||||
LoadString(inst, state->schema->lights[i].name_rsrc,
|
||||
wchars, lengthof(wchars));
|
||||
ComboBox_AddString(game_light_ctl, wchars);
|
||||
|
||||
if (state->bound
|
||||
&& state->schema->lights[i].bit == *state->game_light) {
|
||||
ComboBox_SetCurSel(game_light_ctl, i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
hid_light_ctl = GetDlgItem(hwnd, IDC_LIGHT);
|
||||
|
||||
hid_mgr_lock();
|
||||
|
||||
if (!hid_stub_get_lights(state->ml->hid, NULL, &nlights)) {
|
||||
goto size_fail;
|
||||
}
|
||||
|
||||
if (state->ml->light_no >= nlights) {
|
||||
goto bounds_fail;
|
||||
}
|
||||
|
||||
lights = xmalloc(sizeof(*lights) * nlights);
|
||||
|
||||
if (!hid_stub_get_lights(state->ml->hid, lights, &nlights)) {
|
||||
goto data_fail;
|
||||
}
|
||||
|
||||
usages_get(chars, lengthof(chars), lights[state->ml->light_no].usage);
|
||||
MultiByteToWideChar(CP_UTF8, 0, chars, -1, wchars, lengthof(wchars));
|
||||
|
||||
SetWindowText(hid_light_ctl, wchars);
|
||||
|
||||
data_fail:
|
||||
free(lights);
|
||||
|
||||
bounds_fail:
|
||||
size_fail:
|
||||
hid_mgr_unlock();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR bind_light_handle_ok(HWND hwnd)
|
||||
{
|
||||
struct bind_light_state *state;
|
||||
int pos;
|
||||
HWND game_light_ctl;
|
||||
|
||||
state = (struct bind_light_state *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
game_light_ctl = GetDlgItem(hwnd, IDC_GAME_LIGHT);
|
||||
pos = ComboBox_GetCurSel(game_light_ctl);
|
||||
|
||||
if (pos <= 0) {
|
||||
*state->bound = false;
|
||||
} else {
|
||||
*state->bound = true;
|
||||
*state->game_light = state->schema->lights[pos - 1].bit;
|
||||
}
|
||||
|
||||
EndDialog(hwnd, TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#ifndef CONFIG_BIND_LIGHT_H
|
||||
#define CONFIG_BIND_LIGHT_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "config/schema.h"
|
||||
|
||||
#include "geninput/mapper.h"
|
||||
|
||||
bool bind_light(HINSTANCE inst, HWND hwnd, const struct schema *schema,
|
||||
const struct mapped_light *ml, uint8_t *game_light, bool *bound);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,127 @@
|
||||
#include <windows.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "config/bind.h"
|
||||
#include "config/resource.h"
|
||||
#include "config/schema.h"
|
||||
#include "config/snap.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
|
||||
struct bind_state {
|
||||
const struct action_def *action;
|
||||
struct mapped_action *ma;
|
||||
struct snap snaps[2];
|
||||
size_t cur_snap;
|
||||
uintptr_t timer_id;
|
||||
};
|
||||
|
||||
static INT_PTR CALLBACK bind_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
static INT_PTR bind_handle_init(HWND hwnd, struct bind_state *self);
|
||||
static INT_PTR bind_handle_tick(HWND hwnd);
|
||||
static INT_PTR bind_handle_cancel(HWND hwnd);
|
||||
static INT_PTR bind_handle_destroy(HWND hwnd);
|
||||
|
||||
bool bind_control(HINSTANCE inst, HWND hwnd, const struct action_def *action,
|
||||
struct mapped_action *ma)
|
||||
{
|
||||
struct bind_state self;
|
||||
bool result;
|
||||
|
||||
self.action = action;
|
||||
self.ma = ma;
|
||||
self.cur_snap = 0;
|
||||
|
||||
snap_init(&self.snaps[1]);
|
||||
snap_init(&self.snaps[0]);
|
||||
|
||||
result = DialogBoxParam(inst, MAKEINTRESOURCE(IDD_BIND), hwnd,
|
||||
bind_dlg_proc, (LPARAM) &self) != 0;
|
||||
|
||||
snap_fini(&self.snaps[0]);
|
||||
snap_fini(&self.snaps[1]);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK bind_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
return bind_handle_init(hwnd, (struct bind_state *) lparam);
|
||||
|
||||
case WM_TIMER:
|
||||
return bind_handle_tick(hwnd);
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wparam)) {
|
||||
case IDCANCEL:
|
||||
return bind_handle_cancel(hwnd);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
case WM_DESTROY:
|
||||
return bind_handle_destroy(hwnd);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR bind_handle_init(HWND hwnd, struct bind_state *self)
|
||||
{
|
||||
HINSTANCE inst;
|
||||
wchar_t str[128];
|
||||
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
LoadString(inst, self->action->name_rsrc, str, lengthof(str));
|
||||
SetWindowText(GetDlgItem(hwnd, IDC_ACTION_NAME), str);
|
||||
|
||||
self->timer_id = SetTimer(hwnd, 0, 17, NULL);
|
||||
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR bind_handle_tick(HWND hwnd)
|
||||
{
|
||||
struct bind_state *self;
|
||||
|
||||
self = (struct bind_state *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
self->cur_snap = !self->cur_snap;
|
||||
|
||||
snap_fini(&self->snaps[self->cur_snap]);
|
||||
snap_init(&self->snaps[self->cur_snap]);
|
||||
|
||||
if (snap_find_edge(&self->snaps[self->cur_snap],
|
||||
&self->snaps[!self->cur_snap], self->ma)) {
|
||||
EndDialog(hwnd, 1);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR bind_handle_cancel(HWND hwnd)
|
||||
{
|
||||
EndDialog(hwnd, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR bind_handle_destroy(HWND hwnd)
|
||||
{
|
||||
struct bind_state *self;
|
||||
|
||||
self = (struct bind_state *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
KillTimer(hwnd, self->timer_id);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef CONFIG_BIND_H
|
||||
#define CONFIG_BIND_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "config/schema.h"
|
||||
|
||||
#include "geninput/mapper.h"
|
||||
|
||||
bool bind_control(HINSTANCE inst, HWND hwnd, const struct action_def *action,
|
||||
struct mapped_action *ma);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,426 @@
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config/bind.h"
|
||||
#include "config/bind-adv.h"
|
||||
#include "config/resource.h"
|
||||
#include "config/schema.h"
|
||||
#include "config/usages.h"
|
||||
|
||||
#include "geninput/input-config.h"
|
||||
#include "geninput/mapper.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/log.h"
|
||||
#include "util/mem.h"
|
||||
#include "util/winres.h"
|
||||
|
||||
static INT_PTR CALLBACK buttons_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
static bool buttons_get_control_name(const struct mapped_action *ma,
|
||||
wchar_t *str, size_t nchars);
|
||||
static INT_PTR buttons_handle_init(HWND hwnd, const PROPSHEETPAGE *psp);
|
||||
static INT_PTR buttons_handle_binding_adv(HWND hwnd);
|
||||
static INT_PTR buttons_handle_binding_clear(HWND hwnd);
|
||||
static INT_PTR buttons_handle_binding_edit(HWND hwnd, BOOL bind_many);
|
||||
static INT_PTR buttons_handle_switch_page(HWND hwnd, NMUPDOWN *n);
|
||||
static INT_PTR buttons_handle_fini(HWND hwnd);
|
||||
static void buttons_update(HWND hwnd);
|
||||
static void buttons_update_bindings(HWND hwnd);
|
||||
static void buttons_update_pager(HWND hwnd);
|
||||
|
||||
struct buttons_tab {
|
||||
const struct schema *schema;
|
||||
uint8_t page_no;
|
||||
uint8_t npages;
|
||||
};
|
||||
|
||||
HPROPSHEETPAGE buttons_tab_create(HINSTANCE inst, const struct schema *schema)
|
||||
{
|
||||
PROPSHEETPAGE psp;
|
||||
|
||||
memset(&psp, 0, sizeof(psp));
|
||||
psp.dwSize = sizeof(psp);
|
||||
psp.dwFlags = PSP_DEFAULT;
|
||||
psp.hInstance = inst;
|
||||
psp.pszTemplate = MAKEINTRESOURCE(IDD_TAB_BUTTONS);
|
||||
psp.pfnDlgProc = buttons_dlg_proc;
|
||||
psp.lParam = (LPARAM) schema;
|
||||
|
||||
return CreatePropertySheetPage(&psp);
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK buttons_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam)
|
||||
{
|
||||
NMHDR *n;
|
||||
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
return buttons_handle_init(hwnd, (const PROPSHEETPAGE *) lparam);
|
||||
|
||||
case WM_NOTIFY:
|
||||
n = (NMHDR *) lparam;
|
||||
|
||||
switch (n->idFrom) {
|
||||
case IDC_PAGE:
|
||||
switch (n->code) {
|
||||
case UDN_DELTAPOS:
|
||||
return buttons_handle_switch_page(hwnd,
|
||||
(NMUPDOWN *) n);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
case IDC_BINDINGS:
|
||||
switch (n->code) {
|
||||
case NM_DBLCLK:
|
||||
return buttons_handle_binding_edit(hwnd, FALSE);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wparam)) {
|
||||
case IDC_BINDING_ADV:
|
||||
return buttons_handle_binding_adv(hwnd);
|
||||
|
||||
case IDC_BINDING_CLEAR:
|
||||
return buttons_handle_binding_clear(hwnd);
|
||||
|
||||
case IDC_BINDING_EDIT:
|
||||
return buttons_handle_binding_edit(hwnd, FALSE);
|
||||
|
||||
case IDC_BINDING_EDIT_MANY:
|
||||
return buttons_handle_binding_edit(hwnd, TRUE);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
case WM_DESTROY:
|
||||
return buttons_handle_fini(hwnd);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR buttons_handle_init(HWND hwnd, const PROPSHEETPAGE *psp)
|
||||
{
|
||||
struct buttons_tab *self;
|
||||
HWND bindings_ctl;
|
||||
HINSTANCE inst;
|
||||
LVCOLUMN col;
|
||||
LVITEM item;
|
||||
wchar_t str[128];
|
||||
size_t i;
|
||||
|
||||
self = xmalloc(sizeof(*self));
|
||||
self->schema = (const struct schema *) psp->lParam;
|
||||
self->page_no = 0;
|
||||
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) self);
|
||||
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
bindings_ctl = GetDlgItem(hwnd, IDC_BINDINGS);
|
||||
|
||||
ListView_SetExtendedListViewStyle(bindings_ctl,
|
||||
LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
|
||||
|
||||
LoadString(inst, IDS_COL_ACTION, str, lengthof(str));
|
||||
|
||||
col.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
|
||||
col.fmt = LVCFMT_LEFT;
|
||||
col.cx = 120;
|
||||
col.pszText = str;
|
||||
|
||||
ListView_InsertColumn(bindings_ctl, 0, &col);
|
||||
|
||||
LoadString(inst, IDS_COL_BUTTON, str, lengthof(str));
|
||||
|
||||
col.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
|
||||
col.fmt = LVCFMT_LEFT;
|
||||
col.cx = 120;
|
||||
col.pszText = str;
|
||||
|
||||
ListView_InsertColumn(bindings_ctl, 1, &col);
|
||||
|
||||
for (i = 0 ; i < self->schema->nactions ; i++) {
|
||||
memset(&item, 0, sizeof(item));
|
||||
|
||||
LoadString(inst, self->schema->actions[i].name_rsrc, str,
|
||||
lengthof(str));
|
||||
|
||||
item.mask = LVIF_TEXT;
|
||||
item.iItem = (int) i;
|
||||
item.iSubItem = 0;
|
||||
item.pszText = str;
|
||||
|
||||
ListView_InsertItem(bindings_ctl, &item);
|
||||
}
|
||||
|
||||
buttons_update(hwnd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void buttons_update(HWND hwnd)
|
||||
{
|
||||
buttons_update_pager(hwnd);
|
||||
buttons_update_bindings(hwnd);
|
||||
|
||||
/* Flickery, but seems to be the only way to avoid label garbling when
|
||||
the page label changes. Need to do better. */
|
||||
InvalidateRect(hwnd, NULL, TRUE);
|
||||
}
|
||||
|
||||
static void buttons_update_pager(HWND hwnd)
|
||||
{
|
||||
struct buttons_tab *self;
|
||||
HINSTANCE inst;
|
||||
wchar_t str[128];
|
||||
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
self = (struct buttons_tab *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
self->npages = mapper_get_npages() + 1;
|
||||
|
||||
rswprintf(str, lengthof(str), inst, IDS_PAGE, self->page_no + 1,
|
||||
self->npages);
|
||||
SetWindowText(GetDlgItem(hwnd, IDC_PAGE_TEXT), str);
|
||||
}
|
||||
|
||||
static void buttons_update_bindings(HWND hwnd)
|
||||
{
|
||||
action_iter_t pos;
|
||||
struct mapped_action ma;
|
||||
struct buttons_tab *self;
|
||||
HINSTANCE inst;
|
||||
HWND bindings_ctl;
|
||||
LVITEM item;
|
||||
wchar_t str[128];
|
||||
size_t i;
|
||||
|
||||
self = (struct buttons_tab *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
bindings_ctl = GetDlgItem(hwnd, IDC_BINDINGS);
|
||||
|
||||
/* Clear binding cell text */
|
||||
|
||||
for (i = 0 ; i < self->schema->nactions ; i++) {
|
||||
memset(&item, 0, sizeof(item));
|
||||
|
||||
item.mask = LVIF_TEXT;
|
||||
item.iItem = (int) i;
|
||||
item.iSubItem = 1;
|
||||
item.pszText = L"";
|
||||
|
||||
ListView_SetItem(bindings_ctl, &item);
|
||||
}
|
||||
|
||||
/* Repopulate bindings */
|
||||
|
||||
hid_mgr_lock();
|
||||
|
||||
for (pos = mapper_iterate_actions()
|
||||
; action_iter_is_valid(pos)
|
||||
; action_iter_next(pos)) {
|
||||
if (action_iter_get_page(pos) != self->page_no) {
|
||||
continue;
|
||||
}
|
||||
|
||||
action_iter_get_mapping(pos, &ma);
|
||||
|
||||
if (!buttons_get_control_name(&ma, str, lengthof(str))) {
|
||||
/* Can't read device metadata, device is probably unplugged */
|
||||
LoadString(inst, IDS_NOT_PRESENT, str, lengthof(str));
|
||||
}
|
||||
|
||||
memset(&item, 0, sizeof(item));
|
||||
|
||||
item.mask = LVIF_TEXT;
|
||||
item.iItem = (int) action_iter_get_action(pos);
|
||||
item.iSubItem = 1;
|
||||
item.pszText = str;
|
||||
|
||||
ListView_SetItem(bindings_ctl, &item);
|
||||
}
|
||||
|
||||
action_iter_free(pos);
|
||||
hid_mgr_unlock();
|
||||
}
|
||||
|
||||
static bool buttons_get_control_name(const struct mapped_action *ma,
|
||||
wchar_t *str, size_t nchars)
|
||||
{
|
||||
char chars[128];
|
||||
struct hid_control *controls;
|
||||
size_t ncontrols;
|
||||
|
||||
if (!hid_stub_get_controls(ma->hid, NULL, &ncontrols)) {
|
||||
goto count_fail;
|
||||
}
|
||||
|
||||
controls = xmalloc(ncontrols * sizeof(*controls));
|
||||
|
||||
if (!hid_stub_get_controls(ma->hid, controls, &ncontrols)) {
|
||||
goto data_fail;
|
||||
}
|
||||
|
||||
if (ma->control_no >= ncontrols) {
|
||||
goto bounds_fail;
|
||||
}
|
||||
|
||||
usages_get(chars, lengthof(chars), controls[ma->control_no].usage);
|
||||
MultiByteToWideChar(CP_UTF8, 0, chars, lengthof(chars), str, nchars);
|
||||
|
||||
free(controls);
|
||||
|
||||
return true;
|
||||
|
||||
bounds_fail:
|
||||
data_fail:
|
||||
free(controls);
|
||||
|
||||
count_fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
static INT_PTR buttons_handle_binding_adv(HWND hwnd)
|
||||
{
|
||||
HINSTANCE inst;
|
||||
struct mapped_action ma;
|
||||
struct buttons_tab *self;
|
||||
int action_no;
|
||||
uint8_t bit;
|
||||
bool is_valid;
|
||||
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
self = (struct buttons_tab *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
action_no = ListView_GetSelectionMark(GetDlgItem(hwnd, IDC_BINDINGS));
|
||||
|
||||
if (action_no < 0 || action_no >= (int) self->schema->nactions) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
bit = self->schema->actions[action_no].bit;
|
||||
|
||||
is_valid = mapper_get_action_map((uint8_t) action_no, self->page_no, &ma);
|
||||
|
||||
if (bind_adv(inst, hwnd, &ma, is_valid)) {
|
||||
mapper_set_action_map((uint8_t) action_no, self->page_no, bit, &ma);
|
||||
buttons_update(hwnd);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR buttons_handle_binding_clear(HWND hwnd)
|
||||
{
|
||||
struct buttons_tab *self;
|
||||
int action_no;
|
||||
|
||||
self = (struct buttons_tab *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
action_no = ListView_GetSelectionMark(GetDlgItem(hwnd, IDC_BINDINGS));
|
||||
|
||||
if (action_no < 0 || action_no >= (int) self->schema->nactions) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
mapper_clear_action_map((uint8_t) action_no, self->page_no);
|
||||
buttons_update(hwnd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR buttons_handle_binding_edit(HWND hwnd, BOOL bind_many)
|
||||
{
|
||||
HINSTANCE inst;
|
||||
HWND listview;
|
||||
struct buttons_tab *self;
|
||||
struct mapped_action ma;
|
||||
int action_start;
|
||||
int action_no;
|
||||
uint8_t bit;
|
||||
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
self = (struct buttons_tab *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
listview = GetDlgItem(hwnd, IDC_BINDINGS);
|
||||
|
||||
action_start = ListView_GetSelectionMark(listview);
|
||||
|
||||
if (action_start < 0 || action_start >= (int) self->schema->nactions) {
|
||||
/* wtf... */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
for(action_no = action_start;
|
||||
action_no < self->schema->nactions;
|
||||
action_no++) {
|
||||
// Make sure the next listview item is visible
|
||||
ListView_SetItemState (listview, action_no, LVIS_FOCUSED | LVIS_SELECTED, 0x000F);
|
||||
ListView_EnsureVisible(listview, action_no, FALSE);
|
||||
|
||||
bit = self->schema->actions[action_no].bit;
|
||||
|
||||
if (bind_control(inst, hwnd, &self->schema->actions[action_no], &ma)) {
|
||||
mapper_set_action_map((uint8_t) action_no, self->page_no, bit, &ma);
|
||||
buttons_update(hwnd);
|
||||
|
||||
log_misc("Bind act %d -> dev %p ctl %u range [%d, %d]",
|
||||
self->schema->actions[action_no].bit, ma.hid,
|
||||
(unsigned int) ma.control_no, ma.value_min, ma.value_max);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
if(!bind_many) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR buttons_handle_switch_page(HWND hwnd, NMUPDOWN *n)
|
||||
{
|
||||
struct buttons_tab *self;
|
||||
|
||||
self = (struct buttons_tab *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
/* The buttons on a horizontal spinner are backwards -.- */
|
||||
|
||||
if (n->iDelta > 0 && self->page_no > 0) {
|
||||
self->page_no--;
|
||||
buttons_update(hwnd);
|
||||
} else if (n->iDelta < 0 && self->page_no < self->npages - 1) {
|
||||
self->page_no++;
|
||||
buttons_update(hwnd);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR buttons_handle_fini(HWND hwnd)
|
||||
{
|
||||
struct buttons_tab *self;
|
||||
|
||||
self = (struct buttons_tab *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
free(self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*" />
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
</assembly>
|
||||
@@ -0,0 +1,392 @@
|
||||
// Generated by ResEdit 1.5.11
|
||||
// Copyright (C) 2006-2012
|
||||
// http://www.resedit.net
|
||||
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <richedit.h>
|
||||
#include "resource.h"
|
||||
|
||||
1 RT_MANIFEST config.exe.manifest
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
IDR_USAGES USAGES "config/usages.txt"
|
||||
|
||||
|
||||
|
||||
//
|
||||
// Dialog resources
|
||||
//
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
IDD_ANALOG DIALOG 0, 0, 220, 100
|
||||
STYLE DS_3DLOOK | DS_CENTER | DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW
|
||||
EXSTYLE WS_EX_CONTROLPARENT
|
||||
FONT 8, "Ms Shell Dlg"
|
||||
{
|
||||
GROUPBOX "", IDC_GROUP, 5, 5, 210, 90
|
||||
CONTROL "", IDC_SENSITIVITY, TRACKBAR_CLASS, WS_TABSTOP | TBS_AUTOTICKS, 10, 75, 200, 15
|
||||
LTEXT "Device", IDC_STATIC, 15, 15, 24, 8, SS_LEFT
|
||||
COMBOBOX IDC_DEVICE, 15, 25, 135, 30, WS_GROUP | WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS
|
||||
COMBOBOX IDC_CONTROL, 15, 50, 135, 30, WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS
|
||||
LTEXT "Sensitivity", IDC_STATIC, 15, 65, 32, 8, SS_LEFT
|
||||
LTEXT "Control", IDC_STATIC, 15, 40, 23, 8, SS_LEFT
|
||||
CONTROL "", IDC_POSITION, "spinner", 0x50020000, 160, 15, 50, 50, 0x02002000
|
||||
}
|
||||
|
||||
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
IDD_BIND DIALOG 0, 0, 200, 64
|
||||
STYLE DS_3DLOOK | DS_CENTER | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP
|
||||
CAPTION "Bind action (ESC to cancel)"
|
||||
FONT 8, "Ms Shell Dlg"
|
||||
{
|
||||
CTEXT "Static", IDC_ACTION_NAME, 5, 25, 190, 8, SS_CENTER
|
||||
}
|
||||
|
||||
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
IDD_BIND_ADV DIALOG 0, 0, 242, 175
|
||||
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
|
||||
CAPTION "Binding Editor"
|
||||
FONT 8, "Ms Shell Dlg"
|
||||
{
|
||||
DEFPUSHBUTTON "OK", IDOK, 130, 155, 50, 14
|
||||
PUSHBUTTON "Cancel", IDCANCEL, 185, 155, 50, 14
|
||||
LTEXT "Device", IDC_STATIC, 14, 14, 24, 8, SS_LEFT
|
||||
LTEXT "Control", IDC_STATIC, 14, 34, 23, 8, SS_LEFT
|
||||
GROUPBOX "Raw Control Value", IDC_STATIC, 5, 55, 230, 95
|
||||
LTEXT "Limits", IDC_STATIC, 14, 88, 18, 8, SS_LEFT
|
||||
LTEXT "Binding", IDC_STATIC, 14, 108, 24, 8, SS_LEFT
|
||||
LTEXT "Current Value", IDC_STATIC, 14, 128, 44, 8, SS_LEFT
|
||||
LTEXT "Minimum", IDC_STATIC, 80, 70, 28, 8, SS_LEFT
|
||||
LTEXT "Maximum", IDC_STATIC, 160, 70, 30, 8, SS_LEFT
|
||||
COMBOBOX IDC_DEVICE, 75, 10, 150, 30, WS_GROUP | WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST | CBS_HASSTRINGS
|
||||
COMBOBOX IDC_CONTROL, 75, 30, 150, 20, WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST | CBS_HASSTRINGS
|
||||
EDITTEXT IDC_LIMIT_MIN, 75, 85, 70, 14, NOT WS_TABSTOP | ES_AUTOHSCROLL | ES_READONLY
|
||||
EDITTEXT IDC_LIMIT_MAX, 155, 85, 70, 14, NOT WS_TABSTOP | ES_AUTOHSCROLL | ES_READONLY
|
||||
EDITTEXT IDC_BINDING_MIN, 75, 105, 70, 14, ES_AUTOHSCROLL | ES_NUMBER
|
||||
EDITTEXT IDC_BINDING_MAX, 155, 105, 70, 14, ES_AUTOHSCROLL | ES_NUMBER
|
||||
EDITTEXT IDC_CURRENT, 75, 125, 150, 14, NOT WS_TABSTOP | ES_CENTER | ES_AUTOHSCROLL | ES_READONLY
|
||||
}
|
||||
|
||||
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
IDD_BIND_LIGHT DIALOG 0, 0, 242, 76
|
||||
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
|
||||
CAPTION "Light Binding"
|
||||
FONT 8, "Ms Shell Dlg"
|
||||
{
|
||||
DEFPUSHBUTTON "OK", IDOK, 130, 55, 50, 14
|
||||
PUSHBUTTON "Cancel", IDCANCEL, 185, 55, 50, 14
|
||||
LTEXT "Game Light", IDC_STATIC, 14, 34, 37, 8, SS_LEFT
|
||||
COMBOBOX IDC_GAME_LIGHT, 75, 30, 160, 30, WS_GROUP | WS_TABSTOP | WS_VSCROLL | CBS_DROPDOWNLIST | CBS_HASSTRINGS
|
||||
LTEXT "HID Light", IDC_STATIC, 14, 14, 31, 8, SS_LEFT
|
||||
EDITTEXT IDC_LIGHT, 75, 10, 160, 14, ES_AUTOHSCROLL | ES_READONLY
|
||||
}
|
||||
|
||||
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
IDD_GAME_TYPE DIALOG 0, 0, 205, 70
|
||||
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
|
||||
CAPTION "Game series"
|
||||
FONT 8, "Ms Shell Dlg"
|
||||
{
|
||||
DEFPUSHBUTTON "OK", IDOK, 95, 50, 50, 14
|
||||
PUSHBUTTON "Cancel", IDCANCEL, 150, 50, 50, 14
|
||||
COMBOBOX IDC_GAME_TYPE, 5, 20, 195, 30, WS_GROUP | WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS
|
||||
LTEXT "Select game series:", IDC_STATIC, 5, 10, 62, 8, SS_LEFT
|
||||
}
|
||||
|
||||
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
IDD_READER DIALOG 0, 0, 220, 90
|
||||
STYLE DS_3DLOOK | DS_CENTER | DS_CONTROL | DS_SHELLFONT | WS_VISIBLE | WS_CHILDWINDOW | WS_SYSMENU
|
||||
EXSTYLE WS_EX_CONTROLPARENT
|
||||
FONT 8, "Ms Shell Dlg"
|
||||
{
|
||||
LTEXT "Keyboard device", IDC_STATIC, 15, 20, 54, 8, SS_LEFT
|
||||
COMBOBOX IDC_KBD_DEVICE, 15, 30, 135, 12, WS_GROUP | WS_TABSTOP | CBS_DROPDOWNLIST | CBS_HASSTRINGS
|
||||
LTEXT "Card ID file", IDC_STATIC, 15, 50, 36, 8, SS_LEFT
|
||||
EDITTEXT IDC_CARD_PATH, 15, 60, 135, 14, ES_AUTOHSCROLL
|
||||
PUSHBUTTON "&Browse...", IDC_BROWSE, 155, 60, 50, 14
|
||||
GROUPBOX "", IDC_GROUP, 5, 5, 210, 80
|
||||
LTEXT "Keypad status", IDC_STATIC, 155, 20, 46, 8, SS_LEFT
|
||||
LTEXT "", IDC_KEYPAD_STATE, 160, 30, 45, 12, SS_LEFT | SS_CENTERIMAGE
|
||||
}
|
||||
|
||||
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
IDD_TAB_ANALOGS DIALOG 0, 0, 220, 215
|
||||
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
|
||||
CAPTION "Analogs"
|
||||
FONT 8, "Ms Shell Dlg"
|
||||
{
|
||||
LTEXT "", IDC_STATIC, 0, 0, 8, 8, SS_LEFT
|
||||
}
|
||||
|
||||
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
IDD_TAB_BUTTONS DIALOG 0, 0, 220, 215
|
||||
STYLE DS_3DLOOK | DS_CENTER | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_CHILDWINDOW | WS_SYSMENU
|
||||
CAPTION "Buttons"
|
||||
FONT 8, "Ms Shell Dlg"
|
||||
{
|
||||
CONTROL "Page XX / XX", IDC_PAGE_TEXT, WC_STATIC, NOT WS_GROUP | SS_SIMPLE, 35, 7, 45, 8, WS_EX_LEFT
|
||||
CONTROL "", IDC_BINDINGS, WC_LISTVIEW, WS_TABSTOP | WS_BORDER | LVS_ALIGNLEFT | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | LVS_SINGLESEL | LVS_REPORT, 5, 20, 210, 170, WS_EX_LEFT
|
||||
PUSHBUTTON "&Bind...", IDC_BINDING_EDIT, 5, 195, 50, 14, 0, WS_EX_LEFT
|
||||
PUSHBUTTON "Bind &many...", IDC_BINDING_EDIT_MANY, 58, 195, 50, 14, 0, WS_EX_LEFT
|
||||
PUSHBUTTON "&Edit...", IDC_BINDING_ADV, 111, 195, 50, 14, 0, WS_EX_LEFT
|
||||
PUSHBUTTON "&Clear", IDC_BINDING_CLEAR, 165, 195, 50, 14, 0, WS_EX_LEFT
|
||||
CONTROL "", IDC_PAGE, UPDOWN_CLASS, WS_TABSTOP | UDS_ARROWKEYS | UDS_HORZ, 5, 5, 25, 11, WS_EX_LEFT
|
||||
}
|
||||
|
||||
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
IDD_TAB_LIGHTS DIALOG 0, 0, 220, 215
|
||||
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
|
||||
CAPTION "Lights"
|
||||
FONT 8, "Ms Shell Dlg"
|
||||
{
|
||||
LTEXT "Device", IDC_STATIC, 5, 5, 24, 8, SS_LEFT
|
||||
COMBOBOX IDC_DEVICE, 5, 15, 210, 30, CBS_DROPDOWNLIST | CBS_HASSTRINGS
|
||||
LTEXT "Lights", IDC_STATIC, 5, 33, 20, 8, SS_LEFT
|
||||
CONTROL "", IDC_LIGHT, WC_LISTVIEW, WS_TABSTOP | WS_BORDER | LVS_ALIGNLEFT | LVS_SHOWSELALWAYS | LVS_NOSORTHEADER | LVS_SINGLESEL | LVS_REPORT, 5, 45, 210, 145
|
||||
CTEXT "WARNING: Clicking on a HID light will cause it to illuminate.", IDC_STATIC, 5, 200, 210, 8, SS_CENTER
|
||||
}
|
||||
|
||||
|
||||
|
||||
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
|
||||
IDD_TAB_NETWORK DIALOG 0, 0, 220, 215
|
||||
STYLE DS_3DLOOK | DS_CENTER | DS_MODALFRAME | DS_SHELLFONT | WS_CAPTION | WS_VISIBLE | WS_POPUP | WS_SYSMENU
|
||||
CAPTION "Network"
|
||||
FONT 8, "Ms Shell Dlg"
|
||||
{
|
||||
LTEXT "", IDC_STATIC, 0, 0, 8, 8, SS_LEFT
|
||||
AUTOCHECKBOX "Generate card ID files on insertion if they do not already exist", IDC_AUTOGEN, 5, 200, 206, 8
|
||||
AUTOCHECKBOX "Use top keyboard row for PIN pad input", IDC_ALT_10K, 5, 185, 141, 8
|
||||
}
|
||||
|
||||
|
||||
|
||||
//
|
||||
// String Table resources
|
||||
//
|
||||
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
STRINGTABLE
|
||||
{
|
||||
IDS_APPNAME "BemaniPC Input Configuration"
|
||||
IDS_BAD_GAME_TYPE "Unknown game type: %S"
|
||||
IDS_PAGE "Page %02d / %02d"
|
||||
IDS_COL_BUTTON "Button"
|
||||
IDS_COL_ACTION "Action"
|
||||
IDS_NOT_PRESENT "<Device not present>"
|
||||
IDS_READER_P1 "P1 Card Reader"
|
||||
IDS_READER_P2 "P2 Card Reader"
|
||||
IDS_MUXED_TITLE "Notice"
|
||||
IDS_MUXED_MSG "You have bound both card readers to the same keypad device. As a result, the Num Lock key will be used to select the active card reader: when Num Lock is off, P1 will receive input, and when Num Lock is on, P2 will receive input.\n\nAre you sure you want to use these settings?"
|
||||
IDS_COL_LIGHT_HID "HID Light"
|
||||
IDS_COL_LIGHT_GAME "Game Light"
|
||||
IDS_GENERIC_TEST "Test"
|
||||
IDS_GENERIC_SERVICE "Service"
|
||||
IDS_IIDX_SCHEMA "beatmania IIDX"
|
||||
IDS_IIDX_P1_1 "P1 1"
|
||||
IDS_IIDX_P1_2 "P1 2"
|
||||
IDS_IIDX_P1_3 "P1 3"
|
||||
IDS_IIDX_P1_4 "P1 4"
|
||||
IDS_IIDX_P1_5 "P1 5"
|
||||
IDS_IIDX_P1_6 "P1 6"
|
||||
IDS_IIDX_P1_7 "P1 7"
|
||||
IDS_IIDX_P2_1 "P2 1"
|
||||
IDS_IIDX_P2_2 "P2 2"
|
||||
IDS_IIDX_P2_3 "P2 3"
|
||||
IDS_IIDX_P2_4 "P2 4"
|
||||
IDS_IIDX_P2_5 "P2 5"
|
||||
IDS_IIDX_P2_6 "P2 6"
|
||||
IDS_IIDX_P2_7 "P2 7"
|
||||
IDS_IIDX_P1_START "P1 Start"
|
||||
IDS_IIDX_P2_START "P2 Start"
|
||||
IDS_IIDX_VEFX "VEFX"
|
||||
IDS_IIDX_EFFECT "Effect"
|
||||
IDS_IIDX_P1_TT_UP "P1 TT +"
|
||||
IDS_IIDX_P1_TT_DOWN "P1 TT -"
|
||||
IDS_IIDX_P1_TT_STAB "P1 TT +/-"
|
||||
IDS_IIDX_P2_TT_UP "P2 TT +"
|
||||
IDS_IIDX_P2_TT_DOWN "P2 TT -"
|
||||
IDS_IIDX_P2_TT_STAB "P2 TT +/-"
|
||||
IDS_IIDX_P1_TT "P1 Turntable"
|
||||
IDS_IIDX_P2_TT "P2 Turntable"
|
||||
IDS_IIDX_SPOT_1_LIGHT "Spot Light #1"
|
||||
IDS_IIDX_SPOT_2_LIGHT "Spot Light #2"
|
||||
IDS_IIDX_SPOT_3_LIGHT "Spot Light #3"
|
||||
IDS_IIDX_SPOT_4_LIGHT "Spot Light #4"
|
||||
IDS_IIDX_SPOT_5_LIGHT "Spot Light #5"
|
||||
IDS_IIDX_SPOT_6_LIGHT "Spot Light #6"
|
||||
IDS_IIDX_SPOT_7_LIGHT "Spot Light #7"
|
||||
IDS_IIDX_SPOT_8_LIGHT "Spot Light #8"
|
||||
IDS_IIDX_NEON_LIGHT "Top Neons"
|
||||
IDS_DDR_SCHEMA "Dance Dance Revolution"
|
||||
IDS_DDR_P1_START "P1 Start"
|
||||
IDS_DDR_P1_MENU_UP "P1 Menu Up"
|
||||
IDS_DDR_P1_MENU_DOWN "P1 Menu Down"
|
||||
IDS_DDR_P1_MENU_LEFT "P1 Menu Left"
|
||||
IDS_DDR_P1_MENU_RIGHT "P1 Menu Right"
|
||||
IDS_DDR_P1_UP "P1 Up"
|
||||
IDS_DDR_P1_DOWN "P1 Down"
|
||||
IDS_DDR_P1_LEFT "P1 Left"
|
||||
IDS_DDR_P1_RIGHT "P1 Right"
|
||||
IDS_DDR_P2_START "P2 Start"
|
||||
IDS_DDR_P2_MENU_UP "P2 Menu Up"
|
||||
IDS_DDR_P2_MENU_DOWN "P2 Menu Down"
|
||||
IDS_DDR_P2_MENU_LEFT "P2 Menu Left"
|
||||
IDS_DDR_P2_MENU_RIGHT "P2 Menu Right"
|
||||
IDS_DDR_P2_UP "P2 Up"
|
||||
IDS_DDR_P2_DOWN "P2 Down"
|
||||
IDS_DDR_P2_LEFT "P2 Left"
|
||||
IDS_DDR_P2_RIGHT "P2 Right"
|
||||
IDS_DDR_P1_MENU_LIGHT "P1 Menu Lights"
|
||||
IDS_DDR_P1_TOP_LIGHT "P1 Marquee Top Light"
|
||||
IDS_DDR_P1_BOTTOM_LIGHT "P1 Marquee Bottom Light"
|
||||
IDS_DDR_P2_MENU_LIGHT "P2 Menu Lights"
|
||||
IDS_DDR_P2_TOP_LIGHT "P2 Marquee Top Light"
|
||||
IDS_DDR_P2_BOTTOM_LIGHT "P2 Marquee Bottom Light"
|
||||
IDS_DDR_BASS_LIGHT "Bass Neons"
|
||||
IDS_PNM_SCHEMA "pop'n music"
|
||||
IDS_PNM_BTN1 "Button 1"
|
||||
IDS_PNM_BTN2 "Button 2"
|
||||
IDS_PNM_BTN3 "Button 3"
|
||||
IDS_PNM_BTN4 "Button 4"
|
||||
IDS_PNM_BTN5 "Button 5"
|
||||
IDS_PNM_BTN6 "Button 6"
|
||||
IDS_PNM_BTN7 "Button 7"
|
||||
IDS_PNM_BTN8 "Button 8"
|
||||
IDS_PNM_BTN9 "Button 9"
|
||||
IDS_JB_SCHEMA "Jubeat"
|
||||
IDS_JB_PANEL1 "Panel 1"
|
||||
IDS_JB_PANEL2 "Panel 2"
|
||||
IDS_JB_PANEL3 "Panel 3"
|
||||
IDS_JB_PANEL4 "Panel 4"
|
||||
IDS_JB_PANEL5 "Panel 5"
|
||||
IDS_JB_PANEL6 "Panel 6"
|
||||
IDS_JB_PANEL7 "Panel 7"
|
||||
IDS_JB_PANEL8 "Panel 8"
|
||||
IDS_JB_PANEL9 "Panel 9"
|
||||
IDS_JB_PANEL10 "Panel 10"
|
||||
IDS_JB_PANEL11 "Panel 11"
|
||||
IDS_JB_PANEL12 "Panel 12"
|
||||
IDS_JB_PANEL13 "Panel 13"
|
||||
IDS_JB_PANEL14 "Panel 14"
|
||||
IDS_JB_PANEL15 "Panel 15"
|
||||
IDS_JB_PANEL16 "Panel 16"
|
||||
IDS_JB_RGB_FRONT_R "RGB Front R"
|
||||
IDS_JB_RGB_FRONT_G "RGB Front G"
|
||||
IDS_JB_RGB_FRONT_B "RGB Front B"
|
||||
IDS_JB_RGB_TOP_R "RGB Top R"
|
||||
IDS_JB_RGB_TOP_G "RGB Top G"
|
||||
IDS_JB_RGB_TOP_B "RGB Top B"
|
||||
IDS_JB_RGB_LEFT_R "RGB Left R"
|
||||
IDS_JB_RGB_LEFT_G "RGB Left G"
|
||||
IDS_JB_RGB_LEFT_B "RGB Left B"
|
||||
IDS_JB_RGB_RIGHT_R "RGB Right R"
|
||||
IDS_JB_RGB_RIGHT_G "RGB Right G"
|
||||
IDS_JB_RGB_RIGHT_B "RGB Right B"
|
||||
IDS_JB_RGB_TITLE_R "RGB Title R"
|
||||
IDS_JB_RGB_TITLE_G "RGB Title G"
|
||||
IDS_JB_RGB_TITLE_B "RGB Title B"
|
||||
IDS_JB_RGB_WOOFER_R "RGB Woofer R"
|
||||
IDS_JB_RGB_WOOFER_G "RGB Woofer G"
|
||||
IDS_JB_RGB_WOOFER_B "RGB Woofer B"
|
||||
IDS_SDVX_SCHEMA "Sound Voltex"
|
||||
IDS_SDVX_START "Start"
|
||||
IDS_SDVX_BTN_A "Button A"
|
||||
IDS_SDVX_BTN_B "Button B"
|
||||
IDS_SDVX_BTN_C "Button C"
|
||||
IDS_SDVX_BTN_D "Button D"
|
||||
IDS_SDVX_FX_L "FX-L"
|
||||
IDS_SDVX_FX_R "FX-R"
|
||||
IDS_SDVX_VOL_L "VOL-L"
|
||||
IDS_SDVX_VOL_R "VOL-R"
|
||||
IDS_SDVX_RGB1_R "Wing Left Up R"
|
||||
IDS_SDVX_RGB1_G "Wing Left Up G"
|
||||
IDS_SDVX_RGB1_B "Wing Left Up B"
|
||||
IDS_SDVX_RGB2_R "Wing Right Up R"
|
||||
IDS_SDVX_RGB2_G "Wing Right Up G"
|
||||
IDS_SDVX_RGB2_B "Wing Right Up B"
|
||||
IDS_SDVX_RGB3_R "Wing Left Low R"
|
||||
IDS_SDVX_RGB3_G "Wing Left Low G"
|
||||
IDS_SDVX_RGB3_B "Wing Left Low B"
|
||||
IDS_SDVX_RGB4_R "Wing Right Low R"
|
||||
IDS_SDVX_RGB4_G "Wing Right Low G"
|
||||
IDS_SDVX_RGB4_B "Wing Right Low B"
|
||||
IDS_SDVX_RGB5_R "Woofer R"
|
||||
IDS_SDVX_RGB5_G "Woofer G"
|
||||
IDS_SDVX_RGB5_B "Woofer B"
|
||||
IDS_SDVX_RGB6_R "Controller R"
|
||||
IDS_SDVX_RGB6_G "Controller G"
|
||||
IDS_SDVX_RGB6_B "Controller B"
|
||||
IDS_DM_SCHEMA "Drummania"
|
||||
IDS_DM_START "Start"
|
||||
IDS_DM_MENU_LEFT "Menu Left"
|
||||
IDS_DM_MENU_RIGHT "Menu Right"
|
||||
IDS_DM_HI_HAT "Hi-Hat"
|
||||
IDS_DM_SNARE "Snare"
|
||||
IDS_DM_HIGH_TOM "High Tom"
|
||||
IDS_DM_LOW_TOM "Low Tom"
|
||||
IDS_DM_CYMBAL "Cymbal"
|
||||
IDS_DM_BASS "Bass Drum"
|
||||
IDS_DM_SPEAKER_LIGHT "Speakers"
|
||||
IDS_DM_SPOT_LIGHT "Spot Light"
|
||||
IDS_DM_START_LIGHT "Start"
|
||||
IDS_DM_MENU_LIGHT "Menu Buttons"
|
||||
IDS_GF_SCHEMA "Guitar Freaks"
|
||||
IDS_GF_P1_START "P1 Start"
|
||||
IDS_GF_P1_PICK "P1 Pick"
|
||||
IDS_GF_P1_PICK_A "P1 Pick A (Guitar Hero compatible)"
|
||||
IDS_GF_P1_PICK_B "P1 Pick B (Guitar Hero compatible)"
|
||||
IDS_GF_P1_WAIL "P1 Wail"
|
||||
IDS_GF_P1_EFFECT "P1 Effect"
|
||||
IDS_GF_P1_RED "P1 Red"
|
||||
IDS_GF_P1_GREEN "P1 Green"
|
||||
IDS_GF_P1_BLUE "P1 Blue"
|
||||
IDS_GF_P2_START "P2 Start"
|
||||
IDS_GF_P2_PICK "P2 Pick"
|
||||
IDS_GF_P2_PICK_A "P2 Pick A (Guitar Hero compatible)"
|
||||
IDS_GF_P2_PICK_B "P2 Pick B (Guitar Hero compatible)"
|
||||
IDS_GF_P2_WAIL "P2 Wail"
|
||||
IDS_GF_P2_EFFECT "P2 Effect"
|
||||
IDS_GF_P2_RED "P2 Red"
|
||||
IDS_GF_P2_GREEN "P2 Green"
|
||||
IDS_GF_P2_BLUE "P2 Blue"
|
||||
IDS_GF_P1_SPOT_LIGHT "P1 Spotlight"
|
||||
IDS_GF_P2_SPOT_LIGHT "P2 Spotlight"
|
||||
IDS_RB_SCHEMA "Reflec Beat"
|
||||
IDS_BST_SCHEMA "BeatStream"
|
||||
IDS_IIDX_PANEL_SCHEMA "beatmania IIDX Effector Panel"
|
||||
IDS_IIDX_PANEL_S1_UP "Effector Slider 1 Up"
|
||||
IDS_IIDX_PANEL_S1_DOWN "Effector Slider 1 Down"
|
||||
IDS_IIDX_PANEL_S2_UP "Effector Slider 2 Up"
|
||||
IDS_IIDX_PANEL_S2_DOWN "Effector Slider 2 Down"
|
||||
IDS_IIDX_PANEL_S3_UP "Effector Slider 3 Up"
|
||||
IDS_IIDX_PANEL_S3_DOWN "Effector Slider 3 Down"
|
||||
IDS_IIDX_PANEL_S4_UP "Effector Slider 4 Up"
|
||||
IDS_IIDX_PANEL_S4_DOWN "Effector Slider 4 Down"
|
||||
IDS_IIDX_PANEL_S5_UP "Effector Slider 5 Up"
|
||||
IDS_IIDX_PANEL_S5_DOWN "Effector Slider 5 Down"
|
||||
IDS_IIDX_PANEL_S1 "Effector Slider 1"
|
||||
IDS_IIDX_PANEL_S2 "Effector Slider 2"
|
||||
IDS_IIDX_PANEL_S3 "Effector Slider 3"
|
||||
IDS_IIDX_PANEL_S4 "Effector Slider 4"
|
||||
IDS_IIDX_PANEL_S5 "Effector Slider 5"
|
||||
}
|
||||
@@ -0,0 +1,489 @@
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
#include <commdlg.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include "config/resource.h"
|
||||
#include "config/schema.h"
|
||||
|
||||
#include "eamio/eam-config.h"
|
||||
|
||||
#include "geninput/hid-mgr.h"
|
||||
#include "geninput/input-config.h"
|
||||
#include "geninput/kbd.h"
|
||||
|
||||
#include "util/array.h"
|
||||
#include "util/defs.h"
|
||||
#include "util/log.h"
|
||||
#include "util/mem.h"
|
||||
#include "util/str.h"
|
||||
|
||||
/* You may or may not have noticed that there is a blank label in the Network
|
||||
tab's dialog resource definition. This is a consequence of the way that
|
||||
Windows UI styles work. WIN32K's (i.e. raw USER32's) GUI routines draw
|
||||
widgets using the Windows 95 chunky bezels and flat surfaces style, but if
|
||||
your app pulls in COMMCTRL v6 or later using an SxS manifest, then it
|
||||
overrides the built-in Win32 widgets with its own glossy versions, in
|
||||
addition to the extended control library that its API provides.
|
||||
|
||||
I'm guessing that top-level windows and dialogs (the tab is a dialog) get
|
||||
subclassed as soon as one of these glossified built-ins gets WM_CREATEd
|
||||
within a window. Hence the presence of the Static control to make sure this
|
||||
takes place.
|
||||
|
||||
Otherwise, you get a flat grey shaded tab body, which looks wrong on Vista
|
||||
and above. */
|
||||
|
||||
struct eam_ui {
|
||||
struct array children;
|
||||
};
|
||||
|
||||
struct eam_unit_ui {
|
||||
const struct eam_unit_def *def;
|
||||
struct array devs;
|
||||
};
|
||||
|
||||
static INT_PTR CALLBACK eam_ui_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
static INT_PTR eam_ui_handle_init(HWND hwnd, const PROPSHEETPAGE *psp);
|
||||
static INT_PTR eam_ui_handle_activate(HWND hwnd);
|
||||
static INT_PTR eam_ui_handle_passivate(HWND hwnd);
|
||||
static INT_PTR eam_ui_handle_tick(HWND hwnd);
|
||||
static INT_PTR eam_ui_handle_change_alt_10k(HWND hwnd);
|
||||
static INT_PTR eam_ui_handle_change_autogen(HWND hwnd);
|
||||
static INT_PTR eam_ui_handle_fini(HWND hwnd);
|
||||
|
||||
static INT_PTR CALLBACK eam_unit_ui_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
static INT_PTR eam_unit_ui_handle_init(HWND hwnd,
|
||||
const struct eam_unit_def *def);
|
||||
static void eam_unit_ui_handle_init_devs(HWND hwnd);
|
||||
static void eam_unit_ui_handle_init_path(HWND hwnd);
|
||||
static INT_PTR eam_unit_ui_handle_browse(HWND hwnd);
|
||||
static INT_PTR eam_unit_ui_handle_change_device(HWND hwnd);
|
||||
static INT_PTR eam_unit_ui_handle_tick(HWND hwnd);
|
||||
static INT_PTR eam_unit_ui_handle_fini(HWND hwnd);
|
||||
|
||||
static const struct eam_io_config_api *eam_io_config_api;
|
||||
|
||||
HPROPSHEETPAGE eam_ui_tab_create(HINSTANCE inst, const struct schema *schema,
|
||||
const struct eam_io_config_api *api)
|
||||
{
|
||||
PROPSHEETPAGE psp;
|
||||
|
||||
eam_io_config_api = api;
|
||||
|
||||
memset(&psp, 0, sizeof(psp));
|
||||
psp.dwSize = sizeof(psp);
|
||||
psp.dwFlags = PSP_DEFAULT;
|
||||
psp.hInstance = inst;
|
||||
psp.pszTemplate = MAKEINTRESOURCE(IDD_TAB_NETWORK);
|
||||
psp.pfnDlgProc = eam_ui_dlg_proc;
|
||||
psp.lParam = (LPARAM) schema;
|
||||
|
||||
return CreatePropertySheetPage(&psp);
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK eam_ui_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam)
|
||||
{
|
||||
const NMHDR *n;
|
||||
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
return eam_ui_handle_init(hwnd, (PROPSHEETPAGE *) lparam);
|
||||
|
||||
case WM_TIMER:
|
||||
return eam_ui_handle_tick(hwnd);
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (HIWORD(wparam)) {
|
||||
case BN_CLICKED:
|
||||
switch (LOWORD(wparam)) {
|
||||
case IDC_AUTOGEN:
|
||||
return eam_ui_handle_change_autogen(hwnd);
|
||||
|
||||
case IDC_ALT_10K:
|
||||
return eam_ui_handle_change_alt_10k(hwnd);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
case WM_NOTIFY:
|
||||
n = (NMHDR *) lparam;
|
||||
|
||||
switch (n->code) {
|
||||
case PSN_SETACTIVE:
|
||||
return eam_ui_handle_activate(hwnd);
|
||||
|
||||
case PSN_KILLACTIVE:
|
||||
return eam_ui_handle_passivate(hwnd);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
case WM_DESTROY:
|
||||
return eam_ui_handle_fini(hwnd);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR eam_ui_handle_init(HWND hwnd, const PROPSHEETPAGE *psp)
|
||||
{
|
||||
struct eam_ui *ui;
|
||||
const struct schema *schema;
|
||||
long ypos;
|
||||
size_t i;
|
||||
HINSTANCE inst;
|
||||
HWND child;
|
||||
RECT r;
|
||||
|
||||
ui = xmalloc(sizeof(*ui));
|
||||
array_init(&ui->children);
|
||||
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM) ui);
|
||||
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
schema = (struct schema *) psp->lParam;
|
||||
|
||||
ypos = 0;
|
||||
|
||||
for (i = 0 ; i < schema->nunits ; i++) {
|
||||
child = CreateDialogParam(inst, MAKEINTRESOURCE(IDD_READER), hwnd,
|
||||
eam_unit_ui_dlg_proc, (LPARAM) &schema->units[i]);
|
||||
|
||||
GetWindowRect(child, &r);
|
||||
SetWindowPos(child, HWND_BOTTOM, 0, ypos, 0, 0,
|
||||
SWP_NOSIZE | SWP_SHOWWINDOW);
|
||||
|
||||
ypos += r.bottom - r.top;
|
||||
|
||||
*array_append(HWND, &ui->children) = child;
|
||||
}
|
||||
|
||||
if (eam_io_config_api->get_autogen()) {
|
||||
SendMessage(GetDlgItem(hwnd, IDC_AUTOGEN), BM_SETCHECK, BST_CHECKED, 0);
|
||||
}
|
||||
|
||||
if (eam_io_config_api->get_alt_10k()) {
|
||||
SendMessage(GetDlgItem(hwnd, IDC_ALT_10K), BM_SETCHECK, BST_CHECKED, 0);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR eam_ui_handle_activate(HWND hwnd)
|
||||
{
|
||||
SetTimer(hwnd, 17, 1, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR eam_ui_handle_passivate(HWND hwnd)
|
||||
{
|
||||
KillTimer(hwnd, 1);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR eam_ui_handle_tick(HWND hwnd)
|
||||
{
|
||||
HWND child;
|
||||
struct eam_ui *ui;
|
||||
size_t i;
|
||||
|
||||
ui = (struct eam_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
mapper_update();
|
||||
|
||||
for (i = 0 ; i < ui->children.nitems ; i++) {
|
||||
child = *array_item(HWND, &ui->children, i);
|
||||
SendMessage(child, WM_USER, 0, 0);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR eam_ui_handle_change_alt_10k(HWND hwnd)
|
||||
{
|
||||
HWND btn;
|
||||
bool alt_10k;
|
||||
|
||||
btn = GetDlgItem(hwnd, IDC_ALT_10K);
|
||||
alt_10k = SendMessage(btn, BM_GETCHECK, 0, 0) == BST_CHECKED;
|
||||
|
||||
eam_io_config_api->set_alt_10k(alt_10k);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR eam_ui_handle_change_autogen(HWND hwnd)
|
||||
{
|
||||
HWND btn;
|
||||
bool autogen;
|
||||
|
||||
btn = GetDlgItem(hwnd, IDC_AUTOGEN);
|
||||
autogen = SendMessage(btn, BM_GETCHECK, 0, 0) == BST_CHECKED;
|
||||
|
||||
eam_io_config_api->set_autogen(autogen);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR eam_ui_handle_fini(HWND hwnd)
|
||||
{
|
||||
struct eam_ui *ui;
|
||||
|
||||
ui = (struct eam_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
array_fini(&ui->children);
|
||||
free(ui);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK eam_unit_ui_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
return eam_unit_ui_handle_init(hwnd,
|
||||
(struct eam_unit_def *) lparam);
|
||||
|
||||
case WM_USER:
|
||||
return eam_unit_ui_handle_tick(hwnd);
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wparam)) {
|
||||
case IDC_KBD_DEVICE:
|
||||
switch (HIWORD(wparam)) {
|
||||
case CBN_SELCHANGE:
|
||||
return eam_unit_ui_handle_change_device(hwnd);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
case IDC_BROWSE:
|
||||
switch (HIWORD(wparam)) {
|
||||
case BN_CLICKED:
|
||||
return eam_unit_ui_handle_browse(hwnd);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
case WM_DESTROY:
|
||||
return eam_unit_ui_handle_fini(hwnd);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR eam_unit_ui_handle_init(HWND hwnd,
|
||||
const struct eam_unit_def *def)
|
||||
{
|
||||
struct eam_unit_ui *ui;
|
||||
wchar_t str[128];
|
||||
HINSTANCE inst;
|
||||
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
|
||||
LoadString(inst, def->label_rsrc, str, lengthof(str));
|
||||
SetWindowText(GetDlgItem(hwnd, IDC_GROUP), str);
|
||||
|
||||
ui = xmalloc(sizeof(*ui));
|
||||
ui->def = def;
|
||||
array_init(&ui->devs);
|
||||
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM) ui);
|
||||
|
||||
eam_unit_ui_handle_init_devs(hwnd);
|
||||
eam_unit_ui_handle_init_path(hwnd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void eam_unit_ui_handle_init_devs(HWND hwnd)
|
||||
{
|
||||
struct eam_unit_ui *ui;
|
||||
uint32_t dev_usage;
|
||||
wchar_t *dev_name;
|
||||
struct hid_stub *hid;
|
||||
size_t nchars;
|
||||
LRESULT index;
|
||||
HWND dev_list;
|
||||
|
||||
ui = (struct eam_unit_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
dev_list = GetDlgItem(hwnd, IDC_KBD_DEVICE);
|
||||
|
||||
*array_append(struct hid_stub *, &ui->devs) = NULL;
|
||||
SendMessage(dev_list, CB_ADDSTRING, 0, (LPARAM) TEXT(""));
|
||||
|
||||
hid_mgr_lock();
|
||||
|
||||
for (hid = hid_mgr_get_first_stub()
|
||||
; hid != NULL
|
||||
; hid = hid_mgr_get_next_stub(hid)) {
|
||||
if (!hid_stub_get_device_usage(hid, &dev_usage)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dev_usage != KBD_DEVICE_USAGE_KEYBOARD
|
||||
&& dev_usage != KBD_DEVICE_USAGE_KEYPAD) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hid_stub_get_name(hid, NULL, &nchars)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
dev_name = xmalloc(nchars * sizeof(*dev_name));
|
||||
|
||||
if (!hid_stub_get_name(hid, dev_name, &nchars)) {
|
||||
free(dev_name);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
index = SendMessage(dev_list, CB_ADDSTRING, 0, (LPARAM) dev_name);
|
||||
|
||||
free(dev_name);
|
||||
|
||||
*array_append(struct hid_stub *, &ui->devs) = hid;
|
||||
|
||||
if (hid == eam_io_config_api->get_keypad_device(ui->def->unit_no)) {
|
||||
SendMessage(dev_list, CB_SETCURSEL, index, 0);
|
||||
}
|
||||
}
|
||||
|
||||
hid_mgr_unlock();
|
||||
}
|
||||
|
||||
static void eam_unit_ui_handle_init_path(HWND hwnd)
|
||||
{
|
||||
struct eam_unit_ui *ui;
|
||||
const char *path;
|
||||
wchar_t *wpath;
|
||||
|
||||
ui = (struct eam_unit_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
path = eam_io_config_api->get_card_path(ui->def->unit_no);
|
||||
|
||||
if (path != NULL) {
|
||||
wpath = str_widen(path);
|
||||
SetWindowText(GetDlgItem(hwnd, IDC_CARD_PATH), wpath);
|
||||
free(wpath);
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR eam_unit_ui_handle_browse(HWND hwnd)
|
||||
{
|
||||
struct eam_unit_ui *ui;
|
||||
char *path_tmp;
|
||||
OPENFILENAME ofn;
|
||||
TCHAR path[MAX_PATH];
|
||||
HWND path_ctl;
|
||||
|
||||
ui = (struct eam_unit_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
path_ctl = GetDlgItem(hwnd, IDC_CARD_PATH);
|
||||
|
||||
path[0] = 0;
|
||||
GetWindowText(path_ctl, path, lengthof(path));
|
||||
|
||||
memset(&ofn, 0, sizeof(ofn));
|
||||
ofn.lStructSize = sizeof(ofn);
|
||||
ofn.hwndOwner = hwnd;
|
||||
ofn.lpstrFile = path;
|
||||
ofn.nMaxFile = lengthof(path);
|
||||
ofn.Flags = OFN_DONTADDTORECENT | OFN_ENABLESIZING | OFN_EXPLORER;
|
||||
|
||||
if (GetOpenFileName(&ofn) && wstr_narrow(path, &path_tmp)) {
|
||||
eam_io_config_api->set_card_path(ui->def->unit_no, path_tmp);
|
||||
free(path_tmp);
|
||||
|
||||
SendMessage(path_ctl, WM_SETTEXT, 0, (LPARAM) path);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR eam_unit_ui_handle_change_device(HWND hwnd)
|
||||
{
|
||||
struct eam_unit_ui *ui;
|
||||
struct hid_stub *hid;
|
||||
HWND dev_list;
|
||||
LRESULT index;
|
||||
|
||||
ui = (struct eam_unit_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
dev_list = GetDlgItem(hwnd, IDC_KBD_DEVICE);
|
||||
|
||||
index = SendMessage(dev_list, CB_GETCURSEL, 0, 0);
|
||||
|
||||
if (index != CB_ERR) {
|
||||
log_assert((size_t) index < ui->devs.nitems);
|
||||
|
||||
hid = *array_item(struct hid_stub *, &ui->devs, index);
|
||||
eam_io_config_api->set_keypad_device(ui->def->unit_no, hid);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR eam_unit_ui_handle_tick(HWND hwnd)
|
||||
{
|
||||
struct eam_unit_ui *ui;
|
||||
uint16_t state;
|
||||
wchar_t state_str[9];
|
||||
|
||||
ui = (struct eam_unit_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
state = eam_io_get_keypad_state(ui->def->unit_no);
|
||||
|
||||
wstr_format(state_str, lengthof(state_str), L"%04x", state);
|
||||
|
||||
SetWindowText(GetDlgItem(hwnd, IDC_KEYPAD_STATE), state_str);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR eam_unit_ui_handle_fini(HWND hwnd)
|
||||
{
|
||||
struct eam_unit_ui *ui;
|
||||
wchar_t path[MAX_PATH];
|
||||
char *tmp;
|
||||
|
||||
ui = (struct eam_unit_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
path[0] = 0;
|
||||
GetWindowText(GetDlgItem(hwnd, IDC_CARD_PATH), path, lengthof(path));
|
||||
|
||||
if (path[0]) {
|
||||
if (wstr_narrow(path, &tmp)) {
|
||||
eam_io_config_api->set_card_path(ui->def->unit_no, tmp);
|
||||
free(tmp);
|
||||
}
|
||||
} else {
|
||||
eam_io_config_api->set_card_path(ui->def->unit_no, NULL);
|
||||
}
|
||||
|
||||
array_fini(&ui->devs);
|
||||
free(ui);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "config/gametype.h"
|
||||
#include "config/resource.h"
|
||||
#include "config/schema.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/log.h"
|
||||
|
||||
static INT_PTR CALLBACK game_type_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
static INT_PTR game_type_handle_init(HWND hwnd);
|
||||
static INT_PTR game_type_handle_ok(HWND hwnd);
|
||||
static INT_PTR game_type_handle_cancel(HWND hwnd);
|
||||
|
||||
const struct schema *game_type_from_str(const char *name)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0 ; i < nschemas ; i++) {
|
||||
if (_stricmp(schemas[i].name, name) == 0) {
|
||||
return &schemas[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct schema *game_type_from_dialog(HINSTANCE inst)
|
||||
{
|
||||
return (struct schema *) DialogBoxParam(inst,
|
||||
MAKEINTRESOURCE(IDD_GAME_TYPE), NULL, game_type_dlg_proc, 0);
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK game_type_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
return game_type_handle_init(hwnd);
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wparam)) {
|
||||
case IDOK:
|
||||
return game_type_handle_ok(hwnd);
|
||||
|
||||
case IDCANCEL:
|
||||
return game_type_handle_cancel(hwnd);
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static INT_PTR game_type_handle_init(HWND hwnd)
|
||||
{
|
||||
HINSTANCE inst;
|
||||
HWND ctl;
|
||||
size_t i;
|
||||
wchar_t text[1024];
|
||||
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
ctl = GetDlgItem(hwnd, IDC_GAME_TYPE);
|
||||
|
||||
for (i = 0 ; i < nschemas ; i++) {
|
||||
LoadString(inst, schemas[i].label, text, lengthof(text));
|
||||
SendMessage(ctl, CB_ADDSTRING, 0, (LPARAM) text);
|
||||
}
|
||||
|
||||
SendMessage(ctl, CB_SETCURSEL, 0, 0);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR game_type_handle_ok(HWND hwnd)
|
||||
{
|
||||
HWND ctl;
|
||||
size_t i;
|
||||
|
||||
ctl = GetDlgItem(hwnd, IDC_GAME_TYPE);
|
||||
i = (size_t) SendMessage(ctl, CB_GETCURSEL, 0, 0);
|
||||
|
||||
log_assert(i < nschemas);
|
||||
|
||||
EndDialog(hwnd, (INT_PTR) &schemas[i]);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR game_type_handle_cancel(HWND hwnd)
|
||||
{
|
||||
EndDialog(hwnd, (INT_PTR) NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
#ifndef CONFIG_GAMETYPE_H
|
||||
#define CONFIG_GAMETYPE_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "config/schema.h"
|
||||
|
||||
const struct schema *game_type_from_str(const char *name);
|
||||
const struct schema *game_type_from_dialog(HINSTANCE inst);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,513 @@
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <commctrl.h>
|
||||
#include <wchar.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "config/bind-light.h"
|
||||
#include "config/resource.h"
|
||||
#include "config/schema.h"
|
||||
#include "config/usages.h"
|
||||
|
||||
#include "geninput/input-config.h"
|
||||
#include "geninput/mapper.h"
|
||||
|
||||
#include "util/array.h"
|
||||
#include "util/defs.h"
|
||||
#include "util/mem.h"
|
||||
|
||||
#define PULSE_DELTA 0.03f
|
||||
|
||||
struct lights_ui {
|
||||
const struct schema *schema;
|
||||
struct array devices;
|
||||
struct hid_stub *hid;
|
||||
struct hid_light *lights;
|
||||
size_t nlights;
|
||||
bool pulse_active;
|
||||
bool pulse_up;
|
||||
size_t pulse_light_no;
|
||||
float pulse_coeff;
|
||||
};
|
||||
|
||||
static INT_PTR CALLBACK lights_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
static INT_PTR lights_handle_init(HWND hwnd, const PROPSHEETPAGE *psp);
|
||||
static void lights_handle_init_devices(HWND hwnd);
|
||||
static void lights_handle_init_device(HWND hwnd, struct hid_stub *hid);
|
||||
static void lights_handle_init_lights(HWND hwnd);
|
||||
static INT_PTR lights_handle_change_dev(HWND hwnd);
|
||||
static INT_PTR lights_handle_highlight_light(HWND hwnd, const NMLISTVIEW *n);
|
||||
static INT_PTR lights_handle_bind_light(HWND hwnd);
|
||||
static INT_PTR lights_handle_pulse_tick(HWND hwnd);
|
||||
static void lights_update_bindings(HWND hwnd);
|
||||
static void lights_pulse_start(HWND hwnd, size_t light_no);
|
||||
static void lights_pulse_stop(HWND hwnd);
|
||||
static INT_PTR lights_handle_fini(HWND hwnd);
|
||||
|
||||
HPROPSHEETPAGE lights_tab_create(HINSTANCE inst, const struct schema *schema)
|
||||
{
|
||||
PROPSHEETPAGE psp;
|
||||
|
||||
memset(&psp, 0, sizeof(psp));
|
||||
psp.dwSize = sizeof(psp);
|
||||
psp.dwFlags = PSP_DEFAULT;
|
||||
psp.hInstance = inst;
|
||||
psp.pszTemplate = MAKEINTRESOURCE(IDD_TAB_LIGHTS);
|
||||
psp.pfnDlgProc = lights_dlg_proc;
|
||||
psp.lParam = (LPARAM) schema;
|
||||
|
||||
return CreatePropertySheetPage(&psp);
|
||||
}
|
||||
|
||||
static INT_PTR CALLBACK lights_dlg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam)
|
||||
{
|
||||
NMHDR *n;
|
||||
|
||||
switch (msg) {
|
||||
case WM_INITDIALOG:
|
||||
return lights_handle_init(hwnd, (const PROPSHEETPAGE *) lparam);
|
||||
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wparam)) {
|
||||
case IDC_DEVICE:
|
||||
switch (HIWORD(wparam)) {
|
||||
case CBN_SELCHANGE:
|
||||
return lights_handle_change_dev(hwnd);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
case WM_NOTIFY:
|
||||
n = (NMHDR *) lparam;
|
||||
|
||||
switch (n->idFrom) {
|
||||
case IDC_LIGHT:
|
||||
switch (n->code) {
|
||||
case LVN_ITEMCHANGED:
|
||||
return lights_handle_highlight_light(hwnd,
|
||||
(NMLISTVIEW *) n);
|
||||
|
||||
case NM_DBLCLK:
|
||||
return lights_handle_bind_light(hwnd);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
||||
case WM_TIMER:
|
||||
return lights_handle_pulse_tick(hwnd);
|
||||
|
||||
case WM_DESTROY:
|
||||
return lights_handle_fini(hwnd);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static INT_PTR lights_handle_init(HWND hwnd, const PROPSHEETPAGE *psp)
|
||||
{
|
||||
struct lights_ui *ui;
|
||||
|
||||
ui = xmalloc(sizeof(*ui));
|
||||
ui->schema = (const struct schema *) psp->lParam;
|
||||
ui->hid = NULL;
|
||||
ui->lights = NULL;
|
||||
array_init(&ui->devices);
|
||||
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (INT_PTR) ui);
|
||||
|
||||
lights_handle_init_devices(hwnd);
|
||||
lights_handle_init_lights(hwnd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void lights_handle_init_devices(HWND hwnd)
|
||||
{
|
||||
struct hid_stub *hid;
|
||||
|
||||
hid_mgr_lock();
|
||||
|
||||
for (hid = hid_mgr_get_first_stub()
|
||||
; hid != NULL
|
||||
; hid = hid_mgr_get_next_stub(hid)) {
|
||||
lights_handle_init_device(hwnd, hid);
|
||||
}
|
||||
|
||||
hid_mgr_unlock();
|
||||
}
|
||||
|
||||
static void lights_handle_init_device(HWND hwnd, struct hid_stub *hid)
|
||||
{
|
||||
wchar_t *chars;
|
||||
size_t nchars;
|
||||
size_t nlights;
|
||||
struct lights_ui *ui;
|
||||
HWND devs;
|
||||
|
||||
if (!hid_stub_get_lights(hid, NULL, &nlights) || nlights == 0) {
|
||||
goto lights_fail;
|
||||
}
|
||||
|
||||
if (!hid_stub_get_name(hid, NULL, &nchars)) {
|
||||
goto name_sz_fail;
|
||||
}
|
||||
|
||||
chars = xmalloc(sizeof(*chars) * nchars);
|
||||
|
||||
if (!hid_stub_get_name(hid, chars, &nchars)) {
|
||||
goto name_fail;
|
||||
}
|
||||
|
||||
ui = (struct lights_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
devs = GetDlgItem(hwnd, IDC_DEVICE);
|
||||
|
||||
*array_append(struct hid_stub *, &ui->devices) = hid;
|
||||
ComboBox_AddString(devs, chars);
|
||||
|
||||
return;
|
||||
|
||||
name_fail:
|
||||
free(chars);
|
||||
|
||||
name_sz_fail:
|
||||
lights_fail:
|
||||
return;
|
||||
}
|
||||
|
||||
static void lights_handle_init_lights(HWND hwnd)
|
||||
{
|
||||
wchar_t str[128];
|
||||
HINSTANCE inst;
|
||||
LVCOLUMN col;
|
||||
HWND lights;
|
||||
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
lights = GetDlgItem(hwnd, IDC_LIGHT);
|
||||
|
||||
ListView_SetExtendedListViewStyle(lights,
|
||||
LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
|
||||
|
||||
LoadString(inst, IDS_COL_LIGHT_HID, str, lengthof(str));
|
||||
|
||||
col.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
|
||||
col.fmt = LVCFMT_LEFT;
|
||||
col.cx = 120;
|
||||
col.pszText = str;
|
||||
|
||||
ListView_InsertColumn(lights, 0, &col);
|
||||
|
||||
LoadString(inst, IDS_COL_LIGHT_GAME, str, lengthof(str));
|
||||
|
||||
col.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
|
||||
col.fmt = LVCFMT_LEFT;
|
||||
col.cx = 120;
|
||||
col.pszText = str;
|
||||
|
||||
ListView_InsertColumn(lights, 1, &col);
|
||||
}
|
||||
|
||||
static INT_PTR lights_handle_change_dev(HWND hwnd)
|
||||
{
|
||||
char chars[256];
|
||||
wchar_t wchars[256];
|
||||
struct lights_ui *ui;
|
||||
struct hid_stub *hid;
|
||||
size_t i;
|
||||
int dev_idx;
|
||||
LVITEM item;
|
||||
HWND devs_ctl;
|
||||
HWND lights_ctl;
|
||||
|
||||
lights_pulse_stop(hwnd);
|
||||
|
||||
ui = (struct lights_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
devs_ctl = GetDlgItem(hwnd, IDC_DEVICE);
|
||||
lights_ctl = GetDlgItem(hwnd, IDC_LIGHT);
|
||||
dev_idx = ComboBox_GetCurSel(devs_ctl);
|
||||
|
||||
if (dev_idx >= (int) ui->devices.nitems) {
|
||||
goto unlocked_fail;
|
||||
}
|
||||
|
||||
ListView_DeleteAllItems(lights_ctl);
|
||||
|
||||
hid = *array_item(struct hid_stub *, &ui->devices, dev_idx);
|
||||
|
||||
hid_mgr_lock();
|
||||
|
||||
if (!hid_stub_get_lights(hid, NULL, &ui->nlights)) {
|
||||
goto locked_fail;
|
||||
}
|
||||
|
||||
ui->lights = xrealloc(ui->lights, sizeof(*ui->lights) * ui->nlights);
|
||||
|
||||
if (!hid_stub_get_lights(hid, ui->lights, &ui->nlights)) {
|
||||
free(ui->lights);
|
||||
ui->lights = NULL;
|
||||
|
||||
goto locked_fail;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < ui->nlights ; i++) {
|
||||
if(ui->lights[i].name[0] != L'\0') {
|
||||
item.pszText = ui->lights[i].name;
|
||||
} else {
|
||||
wchars[0] = L'\0';
|
||||
|
||||
usages_get(chars, lengthof(chars), ui->lights[i].usage);
|
||||
MultiByteToWideChar(CP_UTF8, 0, chars, lengthof(chars), wchars,
|
||||
lengthof(wchars));
|
||||
|
||||
item.pszText = wchars;
|
||||
}
|
||||
|
||||
item.mask = LVIF_TEXT;
|
||||
item.iItem = (int) i;
|
||||
item.iSubItem = 0;
|
||||
|
||||
ListView_InsertItem(lights_ctl, &item);
|
||||
}
|
||||
|
||||
ui->hid = hid;
|
||||
lights_update_bindings(hwnd);
|
||||
|
||||
locked_fail:
|
||||
hid_mgr_unlock();
|
||||
|
||||
unlocked_fail:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR lights_handle_highlight_light(HWND hwnd, const NMLISTVIEW *n)
|
||||
{
|
||||
size_t light_no;
|
||||
|
||||
light_no = n->iItem;
|
||||
|
||||
if (n->uNewState & LVIS_SELECTED) {
|
||||
lights_pulse_start(hwnd, light_no);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR lights_handle_bind_light(HWND hwnd)
|
||||
{
|
||||
struct lights_ui *ui;
|
||||
struct mapped_light ml;
|
||||
uint8_t game_light;
|
||||
bool bound;
|
||||
HINSTANCE inst;
|
||||
HWND lights_ctl;
|
||||
int pos;
|
||||
|
||||
ui = (struct lights_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
lights_ctl = GetDlgItem(hwnd, IDC_LIGHT);
|
||||
|
||||
pos = ListView_GetSelectionMark(lights_ctl);
|
||||
|
||||
if (pos < 0) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ml.hid = ui->hid;
|
||||
ml.light_no = pos;
|
||||
|
||||
if (bind_light(inst, hwnd, ui->schema, &ml, &game_light, &bound)) {
|
||||
if (bound) {
|
||||
mapper_set_light_map(&ml, game_light);
|
||||
} else {
|
||||
mapper_clear_light_map(&ml);
|
||||
}
|
||||
|
||||
lights_update_bindings(hwnd);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static INT_PTR lights_handle_pulse_tick(HWND hwnd)
|
||||
{
|
||||
struct lights_ui *ui;
|
||||
size_t light_no;
|
||||
float intensity;
|
||||
float bias;
|
||||
float scale;
|
||||
float tmp;
|
||||
|
||||
ui = (struct lights_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
if (!ui->pulse_active) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
light_no = ui->pulse_light_no;
|
||||
|
||||
if (ui->hid == NULL || light_no >= ui->nlights) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (ui->pulse_up) {
|
||||
tmp = ui->pulse_coeff + PULSE_DELTA;
|
||||
|
||||
if (tmp > 1.0f) {
|
||||
ui->pulse_coeff = 1.0f;
|
||||
ui->pulse_up = false;
|
||||
} else {
|
||||
ui->pulse_coeff = tmp;
|
||||
}
|
||||
} else {
|
||||
tmp = ui->pulse_coeff - PULSE_DELTA;
|
||||
|
||||
if (tmp < 0.0f) {
|
||||
ui->pulse_coeff = 0.0f;
|
||||
ui->pulse_up = true;
|
||||
} else {
|
||||
ui->pulse_coeff = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
bias = (float) (ui->lights[light_no].value_min);
|
||||
scale = (float) (ui->lights[light_no].value_max
|
||||
- ui->lights[light_no].value_min);
|
||||
|
||||
/* Intensity perception is non-linear. Pulse quadratically. */
|
||||
|
||||
intensity = bias + scale * ui->pulse_coeff * ui->pulse_coeff + 0.5f;
|
||||
|
||||
hid_mgr_lock();
|
||||
hid_stub_set_light(ui->hid, light_no, (int32_t) intensity);
|
||||
hid_mgr_unlock();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void lights_update_bindings(HWND hwnd)
|
||||
{
|
||||
light_iter_t pos;
|
||||
struct mapped_light ml;
|
||||
uint8_t game_light;
|
||||
size_t i;
|
||||
wchar_t wchars[256];
|
||||
struct lights_ui *ui;
|
||||
HINSTANCE inst;
|
||||
HWND lights_ctl;
|
||||
|
||||
ui = (struct lights_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
inst = (HINSTANCE) GetWindowLongPtr(hwnd, GWLP_HINSTANCE);
|
||||
lights_ctl = GetDlgItem(hwnd, IDC_LIGHT);
|
||||
|
||||
for (i = 0 ; i < ui->nlights ; i++) {
|
||||
ListView_SetItemText(lights_ctl, i, 1, NULL);
|
||||
}
|
||||
|
||||
for (pos = mapper_iterate_lights()
|
||||
; light_iter_is_valid(pos)
|
||||
; light_iter_next(pos)) {
|
||||
light_iter_get_mapping(pos, &ml);
|
||||
|
||||
if (ml.hid != ui->hid) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ml.light_no >= ui->nlights) {
|
||||
/* Shouldn't happen unless the HID report descriptor has changed
|
||||
since we last configured this device */
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
game_light = light_iter_get_game_light(pos);
|
||||
|
||||
for (i = 0 ; i < ui->schema->nlights ; i++) {
|
||||
if (ui->schema->lights[i].bit == game_light) {
|
||||
LoadString(inst, ui->schema->lights[i].name_rsrc, wchars,
|
||||
lengthof(wchars));
|
||||
ListView_SetItemText(lights_ctl, ml.light_no, 1, wchars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
light_iter_free(pos);
|
||||
}
|
||||
|
||||
static void lights_pulse_start(HWND hwnd, size_t light_no)
|
||||
{
|
||||
struct lights_ui *ui;
|
||||
int32_t intensity;
|
||||
|
||||
ui = (struct lights_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
if (ui->pulse_active) {
|
||||
lights_pulse_stop(hwnd);
|
||||
}
|
||||
|
||||
/* Start light at max intensity */
|
||||
|
||||
intensity = ui->lights[light_no].value_max;
|
||||
|
||||
hid_mgr_lock();
|
||||
hid_stub_set_light(ui->hid, light_no, intensity);
|
||||
hid_mgr_unlock();
|
||||
|
||||
ui->pulse_active = true;
|
||||
ui->pulse_up = false;
|
||||
ui->pulse_light_no = light_no;
|
||||
ui->pulse_coeff = 1.0f;
|
||||
|
||||
SetTimer(hwnd, 1, 17, NULL);
|
||||
}
|
||||
|
||||
static void lights_pulse_stop(HWND hwnd)
|
||||
{
|
||||
struct lights_ui *ui;
|
||||
size_t light_no;
|
||||
int32_t intensity;
|
||||
|
||||
ui = (struct lights_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
if (!ui->pulse_active) {
|
||||
return;
|
||||
}
|
||||
|
||||
light_no = ui->pulse_light_no;
|
||||
|
||||
if (ui->hid != NULL && light_no < ui->nlights) {
|
||||
intensity = ui->lights[light_no].value_min;
|
||||
|
||||
hid_mgr_lock();
|
||||
hid_stub_set_light(ui->hid, light_no, intensity);
|
||||
hid_mgr_unlock();
|
||||
}
|
||||
|
||||
ui->pulse_active = false;
|
||||
|
||||
KillTimer(hwnd, 1);
|
||||
}
|
||||
|
||||
static INT_PTR lights_handle_fini(HWND hwnd)
|
||||
{
|
||||
struct lights_ui *ui;
|
||||
|
||||
lights_pulse_stop(hwnd);
|
||||
|
||||
ui = (struct lights_ui *) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
|
||||
array_fini(&ui->devices);
|
||||
free(ui->lights);
|
||||
free(ui);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
#include <windows.h>
|
||||
#include <commctrl.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config/gametype.h"
|
||||
#include "config/resource.h"
|
||||
#include "config/schema.h"
|
||||
#include "config/spinner.h"
|
||||
#include "config/usages.h"
|
||||
|
||||
#include "eamio/eam-config.h"
|
||||
|
||||
#include "geninput/input-config.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
#include "util/thread.h"
|
||||
#include "util/winres.h"
|
||||
|
||||
HPROPSHEETPAGE analogs_ui_tab_create(HINSTANCE inst,
|
||||
const struct schema *schema);
|
||||
HPROPSHEETPAGE buttons_tab_create(HINSTANCE inst, const struct schema *schema);
|
||||
HPROPSHEETPAGE lights_tab_create(HINSTANCE inst, const struct schema *schema);
|
||||
HPROPSHEETPAGE eam_ui_tab_create(HINSTANCE inst, const struct schema *schema,
|
||||
const struct eam_io_config_api *eam_io_config_api);
|
||||
|
||||
static void my_fatal(const char *module, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
char buf[1024];
|
||||
|
||||
va_start(ap, fmt);
|
||||
str_vformat(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
MessageBoxA(NULL, buf, NULL, MB_ICONERROR | MB_OK);
|
||||
DebugBreak();
|
||||
|
||||
ExitProcess(-1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
INITCOMMONCONTROLSEX iccx;
|
||||
HINSTANCE inst;
|
||||
HPROPSHEETPAGE psp[4];
|
||||
PROPSHEETHEADER psh;
|
||||
intptr_t result;
|
||||
const struct eam_io_config_api *eam_io_config_api;
|
||||
const struct schema *schema;
|
||||
wchar_t text[1024];
|
||||
int max_light;
|
||||
size_t i;
|
||||
|
||||
inst = GetModuleHandle(NULL);
|
||||
|
||||
log_to_writer(log_writer_debug, NULL);
|
||||
log_to_external(log_impl_misc, log_impl_info, log_impl_warning, my_fatal);
|
||||
|
||||
usages_init(inst);
|
||||
|
||||
memset(&iccx, 0, sizeof(iccx));
|
||||
iccx.dwSize = sizeof(iccx);
|
||||
iccx.dwICC = ICC_STANDARD_CLASSES | ICC_TAB_CLASSES | ICC_WIN95_CLASSES;
|
||||
|
||||
if (!InitCommonControlsEx(&iccx)) {
|
||||
log_fatal("InitCommonControlsEx failed");
|
||||
}
|
||||
|
||||
spinner_init(inst);
|
||||
|
||||
if (argc == 2) {
|
||||
schema = game_type_from_str(argv[1]);
|
||||
|
||||
if (schema == NULL) {
|
||||
rswprintf(text, lengthof(text), inst, IDS_BAD_GAME_TYPE, argv[1]);
|
||||
MessageBox(NULL, text, NULL, MB_ICONERROR | MB_OK);
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
} else {
|
||||
schema = game_type_from_dialog(inst);
|
||||
|
||||
if (schema == NULL) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
input_set_loggers(log_impl_misc, log_impl_info, log_impl_warning,
|
||||
log_impl_fatal);
|
||||
input_init(crt_thread_create, crt_thread_join, crt_thread_destroy);
|
||||
|
||||
eam_io_set_loggers(log_impl_misc, log_impl_info, log_impl_warning,
|
||||
log_impl_fatal);
|
||||
eam_io_init(crt_thread_create, crt_thread_join, crt_thread_destroy);
|
||||
eam_io_config_api = eam_io_get_config_api();
|
||||
|
||||
if (!mapper_config_load(schema->name)) {
|
||||
log_info("Initializing empty config for %s", schema->name);
|
||||
|
||||
max_light = -1;
|
||||
|
||||
for (i = 0 ; i < schema->nlights ; i++) {
|
||||
if (max_light < schema->lights[i].bit) {
|
||||
max_light = schema->lights[i].bit;
|
||||
}
|
||||
}
|
||||
|
||||
mapper_set_nlights((uint8_t) (max_light + 1));
|
||||
mapper_set_nanalogs((uint8_t) schema->nanalogs);
|
||||
}
|
||||
|
||||
memset(&psh, 0, sizeof(psh));
|
||||
psh.dwSize = sizeof(psh);
|
||||
psh.dwFlags = PSH_NOAPPLYNOW | PSH_NOCONTEXTHELP | PSH_USEHICON;
|
||||
psh.hInstance = inst;
|
||||
psh.hIcon = LoadIcon(NULL, IDI_QUESTION);
|
||||
psh.pszCaption = MAKEINTRESOURCE(IDS_APPNAME);
|
||||
psh.phpage = psp;
|
||||
psh.nPages = 0;
|
||||
|
||||
psp[psh.nPages++] = buttons_tab_create(inst, schema);
|
||||
psp[psh.nPages++] = lights_tab_create(inst, schema);
|
||||
|
||||
if (schema->nanalogs > 0) {
|
||||
psp[psh.nPages++] = analogs_ui_tab_create(inst, schema);
|
||||
}
|
||||
|
||||
if (eam_io_config_api != NULL) {
|
||||
psp[psh.nPages++] = eam_ui_tab_create(inst, schema, eam_io_config_api);
|
||||
}
|
||||
|
||||
/* Run GUI */
|
||||
|
||||
result = PropertySheet(&psh);
|
||||
|
||||
/* Save settings and clean up */
|
||||
|
||||
if (result > 0) {
|
||||
if (eam_io_config_api != NULL) {
|
||||
eam_io_config_api->config_save();
|
||||
}
|
||||
|
||||
mapper_config_save(schema->name);
|
||||
}
|
||||
|
||||
eam_io_fini();
|
||||
input_fini();
|
||||
spinner_fini(inst);
|
||||
usages_fini();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
#ifndef IDC_STATIC
|
||||
#define IDC_STATIC (-1)
|
||||
#endif
|
||||
|
||||
#define IDR_USAGES 101
|
||||
#define IDD_TAB_BUTTONS 102
|
||||
#define IDD_TAB_NETWORK 103
|
||||
#define IDD_BIND 104
|
||||
#define IDD_READER 105
|
||||
#define IDD_GAME_TYPE 107
|
||||
#define IDD_ANALOG 109
|
||||
#define IDD_TAB_ANALOGS 111
|
||||
#define IDD_BIND_ADV 113
|
||||
#define IDD_TAB_LIGHTS 115
|
||||
#define IDD_BIND_LIGHT 117
|
||||
#define IDC_GAME_LIGHT 1000
|
||||
#define IDC_KBD_DEVICE 1000
|
||||
#define IDC_AUTOGEN 1001
|
||||
#define IDC_CARD_PATH 1001
|
||||
#define IDC_LIGHT 1001
|
||||
#define IDC_SENSITIVITY 1001
|
||||
#define IDC_ACTION_NAME 1002
|
||||
#define IDC_ALT_10K 1002
|
||||
#define IDC_KEYPAD_STATE 1002
|
||||
#define IDC_GAME_TYPE 1003
|
||||
#define IDC_GROUP 1003
|
||||
#define IDC_LIMIT_MIN 1003
|
||||
#define IDC_BROWSE 1004
|
||||
#define IDC_BINDINGS 1005
|
||||
#define IDC_DEVICE 1005
|
||||
#define IDC_BINDING_EDIT 1006
|
||||
#define IDC_CONTROL 1006
|
||||
#define IDC_BINDING_CLEAR 1007
|
||||
#define IDC_BINDING_MIN 1008
|
||||
#define IDC_PAGE_TEXT 1008
|
||||
#define IDC_POSITION 1008
|
||||
#define IDC_PAGE 1009
|
||||
#define IDC_BINDING_MAX 1010
|
||||
#define IDC_LIMIT_MAX 1011
|
||||
#define IDC_CURRENT 1013
|
||||
#define IDC_BINDING_EDIT_MANY 40000
|
||||
#define IDS_APPNAME 40000
|
||||
#define IDS_BAD_GAME_TYPE 40001
|
||||
#define IDS_PAGE 40002
|
||||
#define IDS_COL_BUTTON 40003
|
||||
#define IDS_COL_ACTION 40004
|
||||
#define IDS_NOT_PRESENT 40005
|
||||
#define IDS_READER_P1 40006
|
||||
#define IDS_READER_P2 40007
|
||||
#define IDS_MUXED_TITLE 40008
|
||||
#define IDS_MUXED_MSG 40009
|
||||
#define IDS_COL_LIGHT_HID 40010
|
||||
#define IDS_COL_LIGHT_GAME 40011
|
||||
#define IDS_GENERIC_TEST 40012
|
||||
#define IDS_GENERIC_SERVICE 40013
|
||||
#define IDS_IIDX_SCHEMA 40014
|
||||
#define IDS_IIDX_P1_1 40015
|
||||
#define IDS_IIDX_P1_2 40016
|
||||
#define IDS_IIDX_P1_3 40017
|
||||
#define IDS_IIDX_P1_4 40018
|
||||
#define IDS_IIDX_P1_5 40019
|
||||
#define IDS_IIDX_P1_6 40020
|
||||
#define IDS_IIDX_P1_7 40021
|
||||
#define IDS_IIDX_P2_1 40022
|
||||
#define IDS_IIDX_P2_2 40023
|
||||
#define IDS_IIDX_P2_3 40024
|
||||
#define IDS_IIDX_P2_4 40025
|
||||
#define IDS_IIDX_P2_5 40026
|
||||
#define IDS_IIDX_P2_6 40027
|
||||
#define IDS_IIDX_P2_7 40028
|
||||
#define IDS_IIDX_P1_START 40029
|
||||
#define IDS_IIDX_P2_START 40030
|
||||
#define IDS_IIDX_VEFX 40031
|
||||
#define IDS_IIDX_EFFECT 40032
|
||||
#define IDS_IIDX_P1_TT_UP 40033
|
||||
#define IDS_IIDX_P1_TT_DOWN 40034
|
||||
#define IDS_IIDX_P1_TT_STAB 40035
|
||||
#define IDS_IIDX_P2_TT_UP 40036
|
||||
#define IDS_IIDX_P2_TT_DOWN 40037
|
||||
#define IDS_IIDX_P2_TT_STAB 40038
|
||||
#define IDS_IIDX_P1_TT 40039
|
||||
#define IDS_IIDX_P2_TT 40040
|
||||
#define IDS_IIDX_SPOT_1_LIGHT 40041
|
||||
#define IDS_IIDX_SPOT_2_LIGHT 40042
|
||||
#define IDS_IIDX_SPOT_3_LIGHT 40043
|
||||
#define IDS_IIDX_SPOT_4_LIGHT 40044
|
||||
#define IDS_IIDX_SPOT_5_LIGHT 40045
|
||||
#define IDS_IIDX_SPOT_6_LIGHT 40046
|
||||
#define IDS_IIDX_SPOT_7_LIGHT 40047
|
||||
#define IDS_IIDX_SPOT_8_LIGHT 40048
|
||||
#define IDS_IIDX_NEON_LIGHT 40049
|
||||
#define IDS_DDR_SCHEMA 40050
|
||||
#define IDS_DDR_P1_START 40051
|
||||
#define IDS_DDR_P1_MENU_UP 40052
|
||||
#define IDS_DDR_P1_MENU_DOWN 40053
|
||||
#define IDS_DDR_P1_MENU_LEFT 40054
|
||||
#define IDS_DDR_P1_MENU_RIGHT 40055
|
||||
#define IDS_DDR_P1_UP 40056
|
||||
#define IDS_DDR_P1_DOWN 40057
|
||||
#define IDS_DDR_P1_LEFT 40058
|
||||
#define IDS_DDR_P1_RIGHT 40059
|
||||
#define IDS_DDR_P2_START 40060
|
||||
#define IDS_DDR_P2_MENU_UP 40061
|
||||
#define IDS_DDR_P2_MENU_DOWN 40062
|
||||
#define IDS_DDR_P2_MENU_LEFT 40063
|
||||
#define IDS_DDR_P2_MENU_RIGHT 40064
|
||||
#define IDS_DDR_P2_UP 40065
|
||||
#define IDS_DDR_P2_DOWN 40066
|
||||
#define IDS_DDR_P2_LEFT 40067
|
||||
#define IDS_DDR_P2_RIGHT 40068
|
||||
#define IDS_DDR_P1_MENU_LIGHT 40069
|
||||
#define IDS_DDR_P1_TOP_LIGHT 40070
|
||||
#define IDS_DDR_P1_BOTTOM_LIGHT 40071
|
||||
#define IDS_DDR_P2_MENU_LIGHT 40072
|
||||
#define IDS_DDR_P2_TOP_LIGHT 40073
|
||||
#define IDS_DDR_P2_BOTTOM_LIGHT 40074
|
||||
#define IDS_DDR_BASS_LIGHT 40075
|
||||
#define IDS_PNM_SCHEMA 40076
|
||||
#define IDS_PNM_BTN1 40077
|
||||
#define IDS_PNM_BTN2 40078
|
||||
#define IDS_PNM_BTN3 40079
|
||||
#define IDS_PNM_BTN4 40080
|
||||
#define IDS_PNM_BTN5 40081
|
||||
#define IDS_PNM_BTN6 40082
|
||||
#define IDS_PNM_BTN7 40083
|
||||
#define IDS_PNM_BTN8 40084
|
||||
#define IDS_PNM_BTN9 40085
|
||||
#define IDS_JB_SCHEMA 40086
|
||||
#define IDS_JB_PANEL1 40087
|
||||
#define IDS_JB_PANEL2 40088
|
||||
#define IDS_JB_PANEL3 40089
|
||||
#define IDS_JB_PANEL4 40090
|
||||
#define IDS_JB_PANEL5 40091
|
||||
#define IDS_JB_PANEL6 40092
|
||||
#define IDS_JB_PANEL7 40093
|
||||
#define IDS_JB_PANEL8 40094
|
||||
#define IDC_BINDING_ADV 40095
|
||||
#define IDS_JB_PANEL9 40095
|
||||
#define IDS_JB_PANEL10 40096
|
||||
#define IDS_JB_PANEL11 40097
|
||||
#define IDS_JB_PANEL12 40098
|
||||
#define IDS_JB_PANEL13 40099
|
||||
#define IDS_JB_PANEL14 40100
|
||||
#define IDS_JB_PANEL15 40101
|
||||
#define IDS_JB_PANEL16 40102
|
||||
#define IDS_SDVX_SCHEMA 40103
|
||||
#define IDS_SDVX_START 40104
|
||||
#define IDS_SDVX_BTN_A 40105
|
||||
#define IDS_SDVX_BTN_B 40106
|
||||
#define IDS_SDVX_BTN_C 40107
|
||||
#define IDS_SDVX_BTN_D 40108
|
||||
#define IDS_SDVX_FX_L 40109
|
||||
#define IDS_SDVX_FX_R 40110
|
||||
#define IDS_SDVX_VOL_L 40111
|
||||
#define IDS_SDVX_VOL_R 40112
|
||||
#define IDS_DM_SCHEMA 40113
|
||||
#define IDS_DM_START 40114
|
||||
#define IDS_DM_MENU_LEFT 40115
|
||||
#define IDS_DM_MENU_RIGHT 40116
|
||||
#define IDS_DM_HI_HAT 40117
|
||||
#define IDS_DM_SNARE 40118
|
||||
#define IDS_DM_HIGH_TOM 40119
|
||||
#define IDS_DM_LOW_TOM 40120
|
||||
#define IDS_DM_CYMBAL 40121
|
||||
#define IDS_DM_BASS 40122
|
||||
#define IDS_DM_SPEAKER_LIGHT 40123
|
||||
#define IDS_DM_SPOT_LIGHT 40124
|
||||
#define IDS_DM_START_LIGHT 40125
|
||||
#define IDS_DM_MENU_LIGHT 40126
|
||||
#define IDS_GF_SCHEMA 40127
|
||||
#define IDS_GF_P1_START 40128
|
||||
#define IDS_GF_P1_PICK 40129
|
||||
#define IDS_GF_P1_PICK_A 40130
|
||||
#define IDS_GF_P1_PICK_B 40131
|
||||
#define IDS_GF_P1_WAIL 40132
|
||||
#define IDS_GF_P1_EFFECT 40133
|
||||
#define IDS_GF_P1_RED 40134
|
||||
#define IDS_GF_P1_GREEN 40135
|
||||
#define IDS_GF_P1_BLUE 40136
|
||||
#define IDS_GF_P2_START 40137
|
||||
#define IDS_GF_P2_PICK 40138
|
||||
#define IDS_GF_P2_PICK_A 40139
|
||||
#define IDS_GF_P2_PICK_B 40140
|
||||
#define IDS_GF_P2_WAIL 40141
|
||||
#define IDS_GF_P2_EFFECT 40142
|
||||
#define IDS_GF_P2_RED 40143
|
||||
#define IDS_GF_P2_GREEN 40144
|
||||
#define IDS_GF_P2_BLUE 40145
|
||||
#define IDS_GF_P1_SPOT_LIGHT 40146
|
||||
#define IDS_GF_P2_SPOT_LIGHT 40147
|
||||
#define IDS_RB_SCHEMA 40148
|
||||
#define IDS_SDVX_RGB1_R 40149
|
||||
#define IDS_SDVX_RGB1_G 40150
|
||||
#define IDS_SDVX_RGB1_B 40151
|
||||
#define IDS_SDVX_RGB2_R 40152
|
||||
#define IDS_SDVX_RGB2_G 40153
|
||||
#define IDS_SDVX_RGB2_B 40154
|
||||
#define IDS_SDVX_RGB3_R 40155
|
||||
#define IDS_SDVX_RGB3_G 40156
|
||||
#define IDS_SDVX_RGB3_B 40157
|
||||
#define IDS_SDVX_RGB4_R 40158
|
||||
#define IDS_SDVX_RGB4_G 40159
|
||||
#define IDS_SDVX_RGB4_B 40160
|
||||
#define IDS_SDVX_RGB5_R 40161
|
||||
#define IDS_SDVX_RGB5_G 40162
|
||||
#define IDS_SDVX_RGB5_B 40163
|
||||
#define IDS_SDVX_RGB6_R 40164
|
||||
#define IDS_SDVX_RGB6_G 40165
|
||||
#define IDS_SDVX_RGB6_B 40166
|
||||
#define IDS_JU5_SCHEMA 40167
|
||||
#define IDS_JB_RGB_FRONT_R 40168
|
||||
#define IDS_JB_RGB_FRONT_G 40169
|
||||
#define IDS_JB_RGB_FRONT_B 40170
|
||||
#define IDS_JB_RGB_TOP_R 40171
|
||||
#define IDS_JB_RGB_TOP_G 40172
|
||||
#define IDS_JB_RGB_TOP_B 40173
|
||||
#define IDS_JB_RGB_LEFT_R 40174
|
||||
#define IDS_JB_RGB_LEFT_G 40175
|
||||
#define IDS_JB_RGB_LEFT_B 40176
|
||||
#define IDS_JB_RGB_RIGHT_R 40177
|
||||
#define IDS_JB_RGB_RIGHT_G 40178
|
||||
#define IDS_JB_RGB_RIGHT_B 40179
|
||||
#define IDS_JB_RGB_TITLE_R 40180
|
||||
#define IDS_JB_RGB_TITLE_G 40181
|
||||
#define IDS_JB_RGB_TITLE_B 40182
|
||||
#define IDS_JB_RGB_WOOFER_R 40183
|
||||
#define IDS_JB_RGB_WOOFER_G 40184
|
||||
#define IDS_JB_RGB_WOOFER_B 40185
|
||||
#define IDS_BST_SCHEMA 40186
|
||||
#define IDS_IIDX_PANEL_SCHEMA 40187
|
||||
#define IDS_IIDX_PANEL_S1_UP 40188
|
||||
#define IDS_IIDX_PANEL_S1_DOWN 40189
|
||||
#define IDS_IIDX_PANEL_S2_UP 40190
|
||||
#define IDS_IIDX_PANEL_S2_DOWN 40191
|
||||
#define IDS_IIDX_PANEL_S3_UP 40192
|
||||
#define IDS_IIDX_PANEL_S3_DOWN 40193
|
||||
#define IDS_IIDX_PANEL_S4_UP 40194
|
||||
#define IDS_IIDX_PANEL_S4_DOWN 40195
|
||||
#define IDS_IIDX_PANEL_S5_UP 40196
|
||||
#define IDS_IIDX_PANEL_S5_DOWN 40197
|
||||
#define IDS_IIDX_PANEL_S1 40198
|
||||
#define IDS_IIDX_PANEL_S2 40199
|
||||
#define IDS_IIDX_PANEL_S3 40200
|
||||
#define IDS_IIDX_PANEL_S4 40201
|
||||
#define IDS_IIDX_PANEL_S5 40202
|
||||
@@ -0,0 +1,391 @@
|
||||
#include "config/resource.h"
|
||||
#include "config/schema.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
|
||||
static const struct action_def dm_actions[] = {
|
||||
{ 0x01, IDS_GENERIC_TEST },
|
||||
{ 0x00, IDS_GENERIC_SERVICE },
|
||||
|
||||
{ 0x08, IDS_DM_START },
|
||||
{ 0x0F, IDS_DM_MENU_LEFT },
|
||||
{ 0x11, IDS_DM_MENU_RIGHT },
|
||||
|
||||
{ 0x0A, IDS_DM_HI_HAT },
|
||||
{ 0x0C, IDS_DM_SNARE },
|
||||
{ 0x0E, IDS_DM_HIGH_TOM },
|
||||
{ 0x10, IDS_DM_LOW_TOM },
|
||||
{ 0x12, IDS_DM_CYMBAL },
|
||||
{ 0x16, IDS_DM_BASS }
|
||||
};
|
||||
|
||||
static const struct light_def dm_lights[] = {
|
||||
{ 0x00, IDS_DM_HI_HAT },
|
||||
{ 0x01, IDS_DM_SNARE },
|
||||
{ 0x02, IDS_DM_HIGH_TOM },
|
||||
{ 0x03, IDS_DM_LOW_TOM },
|
||||
{ 0x04, IDS_DM_CYMBAL },
|
||||
{ 0x09, IDS_DM_BASS },
|
||||
{ 0x0A, IDS_DM_SPEAKER_LIGHT },
|
||||
{ 0x08, IDS_DM_SPOT_LIGHT },
|
||||
{ 0x06, IDS_DM_START_LIGHT },
|
||||
{ 0x07, IDS_DM_MENU_LIGHT }
|
||||
};
|
||||
|
||||
static const struct action_def gf_actions[] = {
|
||||
{ 0x01, IDS_GENERIC_TEST },
|
||||
{ 0x00, IDS_GENERIC_SERVICE },
|
||||
|
||||
{ 0x08, IDS_GF_P1_START },
|
||||
{ 0x0A, IDS_GF_P1_PICK },
|
||||
{ 0x18, IDS_GF_P1_PICK_A },
|
||||
{ 0x19, IDS_GF_P1_PICK_B },
|
||||
{ 0x1C, IDS_GF_P1_EFFECT },
|
||||
{ 0x0C, IDS_GF_P1_WAIL },
|
||||
{ 0x12, IDS_GF_P1_RED },
|
||||
{ 0x14, IDS_GF_P1_GREEN },
|
||||
{ 0x16, IDS_GF_P1_BLUE },
|
||||
|
||||
{ 0x09, IDS_GF_P2_START },
|
||||
{ 0x0B, IDS_GF_P2_PICK },
|
||||
{ 0x1A, IDS_GF_P2_PICK_A },
|
||||
{ 0x1B, IDS_GF_P2_PICK_B },
|
||||
{ 0x1D, IDS_GF_P2_EFFECT },
|
||||
{ 0x0D, IDS_GF_P2_WAIL },
|
||||
{ 0x13, IDS_GF_P2_RED },
|
||||
{ 0x15, IDS_GF_P2_GREEN },
|
||||
{ 0x17, IDS_GF_P2_BLUE }
|
||||
};
|
||||
|
||||
static const struct light_def gf_lights[] = {
|
||||
{ 0x08, IDS_GF_P1_SPOT_LIGHT },
|
||||
{ 0x09, IDS_GF_P2_SPOT_LIGHT },
|
||||
{ 0x0A, IDS_GF_P1_START },
|
||||
{ 0x0B, IDS_GF_P2_START }
|
||||
};
|
||||
|
||||
static const struct action_def iidx_actions[] = {
|
||||
{ 0x1C, IDS_GENERIC_TEST },
|
||||
{ 0x1D, IDS_GENERIC_SERVICE },
|
||||
|
||||
{ 0x08, IDS_IIDX_P1_1 },
|
||||
{ 0x09, IDS_IIDX_P1_2 },
|
||||
{ 0x0A, IDS_IIDX_P1_3 },
|
||||
{ 0x0B, IDS_IIDX_P1_4 },
|
||||
{ 0x0C, IDS_IIDX_P1_5 },
|
||||
{ 0x0D, IDS_IIDX_P1_6 },
|
||||
{ 0x0E, IDS_IIDX_P1_7 },
|
||||
|
||||
{ 0x0F, IDS_IIDX_P2_1 },
|
||||
{ 0x10, IDS_IIDX_P2_2 },
|
||||
{ 0x11, IDS_IIDX_P2_3 },
|
||||
{ 0x12, IDS_IIDX_P2_4 },
|
||||
{ 0x13, IDS_IIDX_P2_5 },
|
||||
{ 0x14, IDS_IIDX_P2_6 },
|
||||
{ 0x15, IDS_IIDX_P2_7 },
|
||||
|
||||
{ 0x18, IDS_IIDX_P1_START },
|
||||
{ 0x19, IDS_IIDX_P2_START },
|
||||
{ 0x1A, IDS_IIDX_VEFX },
|
||||
{ 0x1B, IDS_IIDX_EFFECT },
|
||||
|
||||
{ 0x00, IDS_IIDX_P1_TT_UP },
|
||||
{ 0x01, IDS_IIDX_P1_TT_DOWN },
|
||||
{ 0x02, IDS_IIDX_P1_TT_STAB },
|
||||
|
||||
{ 0x03, IDS_IIDX_P2_TT_UP },
|
||||
{ 0x04, IDS_IIDX_P2_TT_DOWN },
|
||||
{ 0x05, IDS_IIDX_P2_TT_STAB },
|
||||
|
||||
{ 0x20, IDS_IIDX_PANEL_S1_UP },
|
||||
{ 0x21, IDS_IIDX_PANEL_S1_DOWN },
|
||||
|
||||
{ 0x22, IDS_IIDX_PANEL_S2_UP },
|
||||
{ 0x23, IDS_IIDX_PANEL_S2_DOWN },
|
||||
|
||||
{ 0x24, IDS_IIDX_PANEL_S3_UP },
|
||||
{ 0x25, IDS_IIDX_PANEL_S3_DOWN },
|
||||
|
||||
{ 0x26, IDS_IIDX_PANEL_S4_UP },
|
||||
{ 0x27, IDS_IIDX_PANEL_S4_DOWN },
|
||||
|
||||
{ 0x28, IDS_IIDX_PANEL_S5_UP },
|
||||
{ 0x29, IDS_IIDX_PANEL_S5_DOWN }
|
||||
};
|
||||
|
||||
static const struct light_def iidx_lights[] = {
|
||||
{ 0x00, IDS_IIDX_P1_1 },
|
||||
{ 0x01, IDS_IIDX_P1_2 },
|
||||
{ 0x02, IDS_IIDX_P1_3 },
|
||||
{ 0x03, IDS_IIDX_P1_4 },
|
||||
{ 0x04, IDS_IIDX_P1_5 },
|
||||
{ 0x05, IDS_IIDX_P1_6 },
|
||||
{ 0x06, IDS_IIDX_P1_7 },
|
||||
|
||||
{ 0x07, IDS_IIDX_P2_1 },
|
||||
{ 0x08, IDS_IIDX_P2_2 },
|
||||
{ 0x09, IDS_IIDX_P2_3 },
|
||||
{ 0x0A, IDS_IIDX_P2_4 },
|
||||
{ 0x0B, IDS_IIDX_P2_5 },
|
||||
{ 0x0C, IDS_IIDX_P2_6 },
|
||||
{ 0x0D, IDS_IIDX_P2_7 },
|
||||
|
||||
{ 0x18, IDS_IIDX_P1_START },
|
||||
{ 0x19, IDS_IIDX_P2_START },
|
||||
{ 0x1A, IDS_IIDX_VEFX },
|
||||
{ 0x1B, IDS_IIDX_EFFECT },
|
||||
|
||||
{ 0x10, IDS_IIDX_SPOT_1_LIGHT },
|
||||
{ 0x11, IDS_IIDX_SPOT_2_LIGHT },
|
||||
{ 0x12, IDS_IIDX_SPOT_3_LIGHT },
|
||||
{ 0x13, IDS_IIDX_SPOT_4_LIGHT },
|
||||
{ 0x14, IDS_IIDX_SPOT_5_LIGHT },
|
||||
{ 0x15, IDS_IIDX_SPOT_6_LIGHT },
|
||||
{ 0x16, IDS_IIDX_SPOT_7_LIGHT },
|
||||
{ 0x17, IDS_IIDX_SPOT_8_LIGHT },
|
||||
|
||||
{ 0x1F, IDS_IIDX_NEON_LIGHT }
|
||||
};
|
||||
|
||||
static const struct analog_def iidx_analogs[] = {
|
||||
{ 0, IDS_IIDX_P1_TT },
|
||||
{ 1, IDS_IIDX_P2_TT }
|
||||
};
|
||||
|
||||
static const struct action_def ddr_actions[] = {
|
||||
{ 0x04, IDS_GENERIC_TEST },
|
||||
{ 0x06, IDS_GENERIC_SERVICE },
|
||||
|
||||
{ 0x10, IDS_DDR_P1_START },
|
||||
{ 0x00, IDS_DDR_P1_MENU_UP },
|
||||
{ 0x01, IDS_DDR_P1_MENU_DOWN },
|
||||
{ 0x16, IDS_DDR_P1_MENU_LEFT },
|
||||
{ 0x17, IDS_DDR_P1_MENU_RIGHT },
|
||||
{ 0x11, IDS_DDR_P1_UP },
|
||||
{ 0x12, IDS_DDR_P1_DOWN },
|
||||
{ 0x13, IDS_DDR_P1_LEFT },
|
||||
{ 0x14, IDS_DDR_P1_RIGHT },
|
||||
|
||||
{ 0x08, IDS_DDR_P2_START },
|
||||
{ 0x02, IDS_DDR_P2_MENU_UP },
|
||||
{ 0x03, IDS_DDR_P2_MENU_DOWN },
|
||||
{ 0x0E, IDS_DDR_P2_MENU_LEFT },
|
||||
{ 0x0F, IDS_DDR_P2_MENU_RIGHT },
|
||||
{ 0x09, IDS_DDR_P2_UP },
|
||||
{ 0x0A, IDS_DDR_P2_DOWN },
|
||||
{ 0x0B, IDS_DDR_P2_LEFT },
|
||||
{ 0x0C, IDS_DDR_P2_RIGHT }
|
||||
};
|
||||
|
||||
static const struct light_def ddr_lights[] = {
|
||||
/* These are split between non-overlapping P3IO and EXTIO state words */
|
||||
|
||||
{ 0x00, IDS_DDR_P1_MENU_LIGHT },
|
||||
{ 0x07, IDS_DDR_P1_TOP_LIGHT },
|
||||
{ 0x07, IDS_DDR_P1_BOTTOM_LIGHT },
|
||||
|
||||
{ 0x1E, IDS_DDR_P1_UP },
|
||||
{ 0x1D, IDS_DDR_P1_DOWN },
|
||||
{ 0x1C, IDS_DDR_P1_LEFT },
|
||||
{ 0x1B, IDS_DDR_P1_RIGHT },
|
||||
|
||||
{ 0x01, IDS_DDR_P2_MENU_LIGHT },
|
||||
{ 0x05, IDS_DDR_P2_TOP_LIGHT },
|
||||
{ 0x04, IDS_DDR_P2_BOTTOM_LIGHT },
|
||||
|
||||
{ 0x16, IDS_DDR_P2_UP },
|
||||
{ 0x15, IDS_DDR_P2_DOWN },
|
||||
{ 0x14, IDS_DDR_P2_LEFT },
|
||||
{ 0x13, IDS_DDR_P2_RIGHT },
|
||||
|
||||
{ 0x0E, IDS_DDR_BASS_LIGHT }
|
||||
};
|
||||
|
||||
static const struct action_def pnm_actions[] = {
|
||||
{ 0x07, IDS_GENERIC_TEST },
|
||||
{ 0x06, IDS_GENERIC_SERVICE },
|
||||
|
||||
{ 0x08, IDS_PNM_BTN1 },
|
||||
{ 0x09, IDS_PNM_BTN2 },
|
||||
{ 0x0A, IDS_PNM_BTN3 },
|
||||
{ 0x0B, IDS_PNM_BTN4 },
|
||||
{ 0x0C, IDS_PNM_BTN5 },
|
||||
{ 0x0D, IDS_PNM_BTN6 },
|
||||
{ 0x0E, IDS_PNM_BTN7 },
|
||||
{ 0x0F, IDS_PNM_BTN8 },
|
||||
{ 0x10, IDS_PNM_BTN9 }
|
||||
};
|
||||
|
||||
static const struct light_def pnm_lights[] = {
|
||||
{ 0x17, IDS_PNM_BTN1 },
|
||||
{ 0x18, IDS_PNM_BTN2 },
|
||||
{ 0x19, IDS_PNM_BTN3 },
|
||||
{ 0x1A, IDS_PNM_BTN4 },
|
||||
{ 0x1B, IDS_PNM_BTN5 },
|
||||
{ 0x1C, IDS_PNM_BTN6 },
|
||||
{ 0x1D, IDS_PNM_BTN7 },
|
||||
{ 0x1E, IDS_PNM_BTN8 },
|
||||
{ 0x1F, IDS_PNM_BTN9 },
|
||||
};
|
||||
|
||||
static const struct action_def jb_actions[] = {
|
||||
{ 0x10, IDS_GENERIC_TEST },
|
||||
{ 0x11, IDS_GENERIC_SERVICE },
|
||||
|
||||
{ 0x00, IDS_JB_PANEL1 },
|
||||
{ 0x01, IDS_JB_PANEL2 },
|
||||
{ 0x02, IDS_JB_PANEL3 },
|
||||
{ 0x03, IDS_JB_PANEL4 },
|
||||
{ 0x04, IDS_JB_PANEL5 },
|
||||
{ 0x05, IDS_JB_PANEL6 },
|
||||
{ 0x06, IDS_JB_PANEL7 },
|
||||
{ 0x07, IDS_JB_PANEL8 },
|
||||
{ 0x08, IDS_JB_PANEL9 },
|
||||
{ 0x09, IDS_JB_PANEL10 },
|
||||
{ 0x0A, IDS_JB_PANEL11 },
|
||||
{ 0x0B, IDS_JB_PANEL12 },
|
||||
{ 0x0C, IDS_JB_PANEL13 },
|
||||
{ 0x0D, IDS_JB_PANEL14 },
|
||||
{ 0x0E, IDS_JB_PANEL15 },
|
||||
{ 0x0F, IDS_JB_PANEL16 }
|
||||
};
|
||||
|
||||
static const struct light_def jb_lights[] = {
|
||||
{ 0x00, IDS_JB_RGB_FRONT_R },
|
||||
{ 0x01, IDS_JB_RGB_FRONT_G },
|
||||
{ 0x02, IDS_JB_RGB_FRONT_B },
|
||||
{ 0x03, IDS_JB_RGB_TOP_R },
|
||||
{ 0x04, IDS_JB_RGB_TOP_G },
|
||||
{ 0x05, IDS_JB_RGB_TOP_B },
|
||||
{ 0x06, IDS_JB_RGB_LEFT_R },
|
||||
{ 0x07, IDS_JB_RGB_LEFT_G },
|
||||
{ 0x08, IDS_JB_RGB_LEFT_B },
|
||||
{ 0x09, IDS_JB_RGB_RIGHT_R },
|
||||
{ 0x0A, IDS_JB_RGB_RIGHT_G },
|
||||
{ 0x0B, IDS_JB_RGB_RIGHT_B },
|
||||
{ 0x0C, IDS_JB_RGB_TITLE_R },
|
||||
{ 0x0D, IDS_JB_RGB_TITLE_G },
|
||||
{ 0x0E, IDS_JB_RGB_TITLE_B },
|
||||
{ 0x0F, IDS_JB_RGB_WOOFER_R },
|
||||
{ 0x10, IDS_JB_RGB_WOOFER_G },
|
||||
{ 0x11, IDS_JB_RGB_WOOFER_B },
|
||||
};
|
||||
|
||||
static const struct action_def sdvx_actions[] = {
|
||||
{ 0x05, IDS_GENERIC_TEST },
|
||||
{ 0x04, IDS_GENERIC_SERVICE },
|
||||
{ 0x0B, IDS_SDVX_START },
|
||||
{ 0x0A, IDS_SDVX_BTN_A },
|
||||
{ 0x09, IDS_SDVX_BTN_B },
|
||||
{ 0x08, IDS_SDVX_BTN_C },
|
||||
{ 0x15, IDS_SDVX_BTN_D },
|
||||
{ 0x14, IDS_SDVX_FX_L },
|
||||
{ 0x13, IDS_SDVX_FX_R }
|
||||
};
|
||||
|
||||
static const struct light_def sdvx_lights[] = {
|
||||
{ 0x0D, IDS_SDVX_BTN_A },
|
||||
{ 0x0E, IDS_SDVX_BTN_B },
|
||||
{ 0x0F, IDS_SDVX_BTN_C },
|
||||
{ 0x00, IDS_SDVX_BTN_D },
|
||||
{ 0x01, IDS_SDVX_FX_L },
|
||||
{ 0x02, IDS_SDVX_FX_R },
|
||||
{ 0x0C, IDS_SDVX_START },
|
||||
{ 0x10, IDS_SDVX_RGB1_R },
|
||||
{ 0x11, IDS_SDVX_RGB1_G },
|
||||
{ 0x12, IDS_SDVX_RGB1_B },
|
||||
{ 0x13, IDS_SDVX_RGB2_R },
|
||||
{ 0x14, IDS_SDVX_RGB2_G },
|
||||
{ 0x15, IDS_SDVX_RGB2_B },
|
||||
{ 0x16, IDS_SDVX_RGB3_R },
|
||||
{ 0x17, IDS_SDVX_RGB3_G },
|
||||
{ 0x18, IDS_SDVX_RGB3_B },
|
||||
{ 0x19, IDS_SDVX_RGB4_R },
|
||||
{ 0x1A, IDS_SDVX_RGB4_G },
|
||||
{ 0x1B, IDS_SDVX_RGB4_B },
|
||||
{ 0x1C, IDS_SDVX_RGB5_R },
|
||||
{ 0x1D, IDS_SDVX_RGB5_G },
|
||||
{ 0x1E, IDS_SDVX_RGB5_B },
|
||||
{ 0x1F, IDS_SDVX_RGB6_R },
|
||||
{ 0x20, IDS_SDVX_RGB6_G },
|
||||
{ 0x21, IDS_SDVX_RGB6_B }
|
||||
};
|
||||
|
||||
static const struct analog_def sdvx_analogs[] = {
|
||||
{ 0, IDS_SDVX_VOL_L },
|
||||
{ 1, IDS_SDVX_VOL_R }
|
||||
};
|
||||
|
||||
static const struct action_def rb_actions[] = {
|
||||
{ 0x00, IDS_GENERIC_TEST },
|
||||
{ 0x01, IDS_GENERIC_SERVICE }
|
||||
};
|
||||
|
||||
static const struct action_def bst_actions[] = {
|
||||
{ 0x05, IDS_GENERIC_TEST },
|
||||
{ 0x04, IDS_GENERIC_SERVICE },
|
||||
};
|
||||
|
||||
static const struct eam_unit_def schema_eam_unit_defs[] = {
|
||||
{ IDS_READER_P1, 0 },
|
||||
{ IDS_READER_P2, 1 }
|
||||
};
|
||||
|
||||
const struct schema schemas[] = {
|
||||
{ "iidx", IDS_IIDX_SCHEMA,
|
||||
iidx_actions, lengthof(iidx_actions),
|
||||
iidx_lights, lengthof(iidx_lights),
|
||||
iidx_analogs, lengthof(iidx_analogs),
|
||||
schema_eam_unit_defs, 2 },
|
||||
|
||||
{ "pnm", IDS_PNM_SCHEMA,
|
||||
pnm_actions, lengthof(pnm_actions),
|
||||
pnm_lights, lengthof(pnm_lights),
|
||||
NULL, 0,
|
||||
schema_eam_unit_defs, 1 },
|
||||
|
||||
{ "gf", IDS_GF_SCHEMA,
|
||||
gf_actions, lengthof(gf_actions),
|
||||
gf_lights, lengthof(gf_lights),
|
||||
NULL, 0,
|
||||
schema_eam_unit_defs, 2 },
|
||||
|
||||
{ "dm", IDS_DM_SCHEMA,
|
||||
dm_actions, lengthof(dm_actions),
|
||||
dm_lights, lengthof(dm_lights),
|
||||
NULL, 0,
|
||||
schema_eam_unit_defs, 1 },
|
||||
|
||||
{ "ddr", IDS_DDR_SCHEMA,
|
||||
ddr_actions, lengthof(ddr_actions),
|
||||
ddr_lights, lengthof(ddr_lights),
|
||||
NULL, 0,
|
||||
schema_eam_unit_defs, 2 },
|
||||
|
||||
{ "jb", IDS_JB_SCHEMA,
|
||||
jb_actions, lengthof(jb_actions),
|
||||
jb_lights, lengthof(jb_lights),
|
||||
NULL, 0,
|
||||
schema_eam_unit_defs, 1 },
|
||||
|
||||
{ "sdvx", IDS_SDVX_SCHEMA,
|
||||
sdvx_actions, lengthof(sdvx_actions),
|
||||
sdvx_lights, lengthof(sdvx_lights),
|
||||
sdvx_analogs, lengthof(sdvx_analogs),
|
||||
schema_eam_unit_defs, 1 },
|
||||
|
||||
{ "rb", IDS_RB_SCHEMA,
|
||||
rb_actions, lengthof(rb_actions),
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
schema_eam_unit_defs, 1 },
|
||||
|
||||
{ "bst", IDS_BST_SCHEMA,
|
||||
bst_actions, lengthof(bst_actions),
|
||||
NULL, 0,
|
||||
NULL, 0,
|
||||
schema_eam_unit_defs, 1 },
|
||||
};
|
||||
|
||||
const size_t nschemas = lengthof(schemas);
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
#ifndef CONFIG_SCHEMA_H
|
||||
#define CONFIG_SCHEMA_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
struct action_def {
|
||||
uint8_t bit;
|
||||
unsigned int name_rsrc;
|
||||
};
|
||||
|
||||
struct light_def {
|
||||
uint8_t bit;
|
||||
unsigned int name_rsrc;
|
||||
};
|
||||
|
||||
struct analog_def {
|
||||
uint8_t tag;
|
||||
unsigned int label_rsrc;
|
||||
};
|
||||
|
||||
struct eam_unit_def {
|
||||
unsigned int label_rsrc;
|
||||
uint8_t unit_no;
|
||||
};
|
||||
|
||||
struct schema {
|
||||
const char *name;
|
||||
unsigned int label;
|
||||
const struct action_def *actions;
|
||||
size_t nactions;
|
||||
const struct light_def *lights;
|
||||
size_t nlights;
|
||||
const struct analog_def *analogs;
|
||||
size_t nanalogs;
|
||||
const struct eam_unit_def *units;
|
||||
size_t nunits;
|
||||
};
|
||||
|
||||
extern const struct schema schemas[];
|
||||
extern const size_t nschemas;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,247 @@
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config/snap.h"
|
||||
|
||||
#include "geninput/hid-mgr.h"
|
||||
|
||||
#include "util/defs.h"
|
||||
#include "util/log.h"
|
||||
#include "util/mem.h"
|
||||
|
||||
enum snap_control_heuristic {
|
||||
CONTROL_CENTERING_AXIS,
|
||||
CONTROL_MULTISWITCH
|
||||
};
|
||||
|
||||
struct snap_known_control {
|
||||
uint32_t usage;
|
||||
enum snap_control_heuristic heuristic;
|
||||
};
|
||||
|
||||
static struct snap_known_control snap_known_controls[] = {
|
||||
/* X axis */
|
||||
{ 0x00010030, CONTROL_CENTERING_AXIS },
|
||||
|
||||
/* Y axis */
|
||||
{ 0x00010031, CONTROL_CENTERING_AXIS },
|
||||
|
||||
/* Z axis */
|
||||
{ 0x00010032, CONTROL_CENTERING_AXIS },
|
||||
|
||||
/* X rotation */
|
||||
{ 0x00010033, CONTROL_CENTERING_AXIS },
|
||||
|
||||
/* Y rotation */
|
||||
{ 0x00010034, CONTROL_CENTERING_AXIS },
|
||||
|
||||
/* Z rotation */
|
||||
{ 0x00010035, CONTROL_CENTERING_AXIS },
|
||||
|
||||
/* I don't have an adapter that presents a slider/dial/wheel so I don't
|
||||
know how to deal with those things right now */
|
||||
|
||||
/* Hat switch */
|
||||
{ 0x00010039, CONTROL_MULTISWITCH }
|
||||
};
|
||||
|
||||
static bool snap_check_for_edge(const struct hid_control *ctl, int32_t val,
|
||||
int32_t other_val, struct mapped_action *ma);
|
||||
|
||||
void snap_init(struct snap *snap)
|
||||
{
|
||||
size_t i;
|
||||
size_t j;
|
||||
size_t ncontrols;
|
||||
size_t ndevs;
|
||||
struct hid_stub *pos;
|
||||
|
||||
hid_mgr_lock();
|
||||
|
||||
ndevs = 0;
|
||||
|
||||
for (pos = hid_mgr_get_first_stub()
|
||||
; pos != NULL
|
||||
; pos = hid_mgr_get_next_stub(pos)) {
|
||||
|
||||
ndevs++;
|
||||
}
|
||||
|
||||
snap->ndevs = ndevs;
|
||||
snap->devs = xcalloc(ndevs * sizeof(*snap->devs));
|
||||
|
||||
i = 0;
|
||||
|
||||
for (pos = hid_mgr_get_first_stub(), i = 0
|
||||
; pos != NULL && i < ndevs
|
||||
; pos = hid_mgr_get_next_stub(pos), i++) {
|
||||
|
||||
if (!hid_stub_is_attached(pos)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hid_stub_get_controls(pos, NULL, &ncontrols)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
snap->devs[i].hid = pos;
|
||||
snap->devs[i].ncontrols = ncontrols;
|
||||
snap->devs[i].controls = xcalloc(ncontrols
|
||||
* sizeof(struct hid_control));
|
||||
snap->devs[i].states = xcalloc(ncontrols * sizeof(int32_t));
|
||||
|
||||
hid_stub_get_controls(pos, snap->devs[i].controls, &ncontrols);
|
||||
|
||||
for (j = 0 ; j < ncontrols ; j++) {
|
||||
hid_stub_get_value(pos, j, &snap->devs[i].states[j]);
|
||||
}
|
||||
}
|
||||
|
||||
hid_mgr_unlock();
|
||||
}
|
||||
|
||||
bool snap_find_edge(const struct snap *snap, const struct snap *other_snap,
|
||||
struct mapped_action *ma)
|
||||
{
|
||||
const struct hid_control *ctl;
|
||||
int32_t val;
|
||||
int32_t other_val;
|
||||
size_t i;
|
||||
size_t j;
|
||||
|
||||
/* Most of these checks are to ensure some other device didn't sneak in
|
||||
between these two snapshots. If it has, then detecting a state
|
||||
transition becomes a bit awkward so we just say that nothing happened
|
||||
and wait for the next poll period.
|
||||
|
||||
Yes, creating a total input snapshot 60ish times per second while
|
||||
attempting to bind a key isn't exactly the most efficient thing in the
|
||||
world. We don't care, it's just a config program. */
|
||||
|
||||
if (snap->ndevs != other_snap->ndevs) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0 ; i < snap->ndevs ; i++) {
|
||||
if (snap->devs[i].hid != other_snap->devs[i].hid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (snap->devs[i].ncontrols != other_snap->devs[i].ncontrols) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcmp(snap->devs[i].controls, other_snap->devs[i].controls,
|
||||
snap->devs[i].ncontrols * sizeof(struct hid_control)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (j = 0 ; j < snap->devs[i].ncontrols ; j++) {
|
||||
ctl = &snap->devs[i].controls[j];
|
||||
val = snap->devs[i].states[j];
|
||||
other_val = other_snap->devs[i].states[j];
|
||||
|
||||
if (snap_check_for_edge(ctl, val, other_val, ma)) {
|
||||
ma->hid = snap->devs[i].hid;
|
||||
ma->control_no = j;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool snap_check_for_edge(const struct hid_control *ctl, int32_t val,
|
||||
int32_t other_val, struct mapped_action *ma)
|
||||
{
|
||||
size_t i;
|
||||
int32_t range;
|
||||
int32_t dz_min;
|
||||
int32_t dz_max;
|
||||
|
||||
if (val != other_val) {
|
||||
log_misc("Value change on %08x: %d -> %d", ctl->usage, other_val, val);
|
||||
}
|
||||
|
||||
if (ctl->value_max - ctl->value_min == 1) {
|
||||
/* Button-like thing, deal with it the obvious way */
|
||||
if (val == ctl->value_max && val != other_val) {
|
||||
ma->value_min = ctl->value_max;
|
||||
ma->value_max = ctl->value_max;
|
||||
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
/* Here we kinda have to take things on a case by case basis */
|
||||
|
||||
for (i = 0 ; i < lengthof(snap_known_controls) ; i++) {
|
||||
if (snap_known_controls[i].usage != ctl->usage) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (snap_known_controls[i].heuristic) {
|
||||
case CONTROL_CENTERING_AXIS:
|
||||
/* Dead zones keep giving me grief, so I'm going to be
|
||||
super-aggressive and assume a 50%-ish dead zone
|
||||
|
||||
(yes I know the rounding here is a little iffy) */
|
||||
|
||||
range = ctl->value_max - ctl->value_min;
|
||||
dz_min = ctl->value_min + ((range * 1) / 4);
|
||||
dz_max = ctl->value_min + ((range * 3) / 4);
|
||||
|
||||
if (val <= dz_min && other_val > dz_min) {
|
||||
ma->value_min = ctl->value_min;
|
||||
ma->value_max = dz_min;
|
||||
|
||||
return true;
|
||||
} else if (val >= dz_max && other_val < dz_max) {
|
||||
ma->value_min = dz_max;
|
||||
ma->value_max = ctl->value_max;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
case CONTROL_MULTISWITCH:
|
||||
/* Assume positions are discrete. Precisely match any
|
||||
transitioned-to value that isn't a null state. */
|
||||
|
||||
if (val >= ctl->value_min && val <= ctl->value_max
|
||||
&& val != other_val) {
|
||||
ma->value_min = val;
|
||||
ma->value_max = val;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Still haven't found it? Well, we don't know how to determine if this
|
||||
control is being actively pressed or not, so the user will just have
|
||||
to manually key in an advanced binding. */
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void snap_fini(struct snap *snap)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0 ; i < snap->ndevs ; i++) {
|
||||
free(snap->devs[i].states);
|
||||
free(snap->devs[i].controls);
|
||||
}
|
||||
|
||||
free(snap->devs);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef CONFIG_SNAP_H
|
||||
#define CONFIG_SNAP_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "geninput/mapper.h"
|
||||
|
||||
struct snap_dev {
|
||||
struct hid_stub *hid;
|
||||
int32_t *states;
|
||||
struct hid_control *controls;
|
||||
uint32_t ncontrols;
|
||||
};
|
||||
|
||||
struct snap {
|
||||
struct snap_dev *devs;
|
||||
uint32_t ndevs;
|
||||
};
|
||||
|
||||
void snap_init(struct snap *snap);
|
||||
bool snap_find_edge(const struct snap *snap, const struct snap *other_snap,
|
||||
struct mapped_action *ma);
|
||||
void snap_fini(struct snap *snap);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,118 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#define METRIC_COLOR RGB(0, 0, 0)
|
||||
#define METRIC_RADIUS_CIRCLE 0.8f
|
||||
#define METRIC_RADIUS_NOTCH 0.2f
|
||||
#define METRIC_THICKNESS 3
|
||||
|
||||
static const wchar_t spinner_cls[] = L"spinner";
|
||||
|
||||
static LRESULT CALLBACK spinner_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
static LRESULT spinner_handle_paint(HWND hwnd);
|
||||
static LRESULT spinner_handle_update(HWND hwnd, uint8_t pos);
|
||||
|
||||
void spinner_init(HINSTANCE inst)
|
||||
{
|
||||
WNDCLASSEX wcx;
|
||||
|
||||
memset(&wcx, 0, sizeof(wcx));
|
||||
wcx.cbSize = sizeof(wcx);
|
||||
wcx.lpfnWndProc = spinner_wnd_proc;
|
||||
wcx.hInstance = inst;
|
||||
wcx.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
|
||||
wcx.lpszClassName = spinner_cls;
|
||||
|
||||
RegisterClassEx(&wcx);
|
||||
}
|
||||
|
||||
static LRESULT CALLBACK spinner_wnd_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam)
|
||||
{
|
||||
switch (msg) {
|
||||
case WM_CREATE:
|
||||
SetWindowLong(hwnd, GWLP_USERDATA, 0);
|
||||
|
||||
return TRUE;
|
||||
|
||||
case WM_PAINT:
|
||||
return spinner_handle_paint(hwnd);
|
||||
|
||||
case WM_USER:
|
||||
return spinner_handle_update(hwnd, (uint8_t) lparam);
|
||||
|
||||
default:
|
||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
}
|
||||
|
||||
static LRESULT spinner_handle_paint(HWND hwnd)
|
||||
{
|
||||
HDC dc;
|
||||
HPEN pen;
|
||||
PAINTSTRUCT ps;
|
||||
RECT r;
|
||||
float cx;
|
||||
float cy;
|
||||
float dx;
|
||||
float dy;
|
||||
float theta;
|
||||
uint8_t itheta;
|
||||
|
||||
/* GWLP_USERDATA angle has 256 steps in a complete revolution.
|
||||
To convert to radians, multiply by (2 * PI / 256). */
|
||||
|
||||
itheta = (uint8_t) GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||
theta = itheta * 0.0245437f;
|
||||
|
||||
GetWindowRect(hwnd, &r);
|
||||
|
||||
cx = (r.right - r.left) / 2.0f;
|
||||
cy = (r.bottom - r.top) / 2.0f;
|
||||
|
||||
dc = BeginPaint(hwnd, &ps);
|
||||
|
||||
pen = CreatePen(PS_SOLID, METRIC_THICKNESS, METRIC_COLOR);
|
||||
SelectObject(dc, pen);
|
||||
SelectObject(dc, GetStockObject(WHITE_BRUSH));
|
||||
|
||||
Ellipse(dc,
|
||||
(int) (cx * (1.0f - METRIC_RADIUS_CIRCLE)),
|
||||
(int) (cy * (1.0f - METRIC_RADIUS_CIRCLE)),
|
||||
(int) (cx * (1.0f + METRIC_RADIUS_CIRCLE)),
|
||||
(int) (cy * (1.0f + METRIC_RADIUS_CIRCLE)));
|
||||
|
||||
dx = sinf(theta);
|
||||
dy = -cosf(theta);
|
||||
|
||||
MoveToEx(dc,
|
||||
(int) (cx * (1.0f + dx * METRIC_RADIUS_NOTCH)),
|
||||
(int) (cy * (1.0f + dy * METRIC_RADIUS_NOTCH)), NULL);
|
||||
|
||||
LineTo(dc,
|
||||
(int) (cx * (1.0f + dx * METRIC_RADIUS_CIRCLE)),
|
||||
(int) (cy * (1.0f + dy * METRIC_RADIUS_CIRCLE)));
|
||||
|
||||
DeleteObject(pen);
|
||||
EndPaint(hwnd, &ps);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static LRESULT spinner_handle_update(HWND hwnd, uint8_t pos)
|
||||
{
|
||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM) pos);
|
||||
InvalidateRect(hwnd, NULL, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void spinner_fini(HINSTANCE inst)
|
||||
{
|
||||
UnregisterClass(spinner_cls, inst);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#ifndef CONFIG_SPINNER_H
|
||||
#define CONFIG_SPINNER_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
void spinner_init(HINSTANCE inst);
|
||||
void spinner_fini(HINSTANCE inst);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,177 @@
|
||||
#include <windows.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "config/resource.h"
|
||||
|
||||
#include "util/array.h"
|
||||
#include "util/log.h"
|
||||
#include "util/str.h"
|
||||
#include "util/winres.h"
|
||||
|
||||
struct usage {
|
||||
uint16_t id;
|
||||
char name[128];
|
||||
};
|
||||
|
||||
struct usage_page {
|
||||
uint16_t id;
|
||||
struct array usages;
|
||||
char wildcard[128];
|
||||
};
|
||||
|
||||
static struct array usages;
|
||||
|
||||
static bool usages_begin_page(const char *line, struct usage_page *page);
|
||||
static bool usages_read_usage(const char *line, struct usage_page *page);
|
||||
|
||||
void usages_init(HINSTANCE inst)
|
||||
{
|
||||
struct resource res;
|
||||
struct usage_page *cur_page;
|
||||
struct usage_page tmp_page;
|
||||
char line[512];
|
||||
size_t line_no;
|
||||
size_t nchars;
|
||||
|
||||
resource_open(&res, inst, "USAGES", IDR_USAGES);
|
||||
array_init(&usages);
|
||||
|
||||
cur_page = NULL;
|
||||
line_no = 0;
|
||||
|
||||
while (resource_fgets(&res, line, sizeof(line))) {
|
||||
line_no++;
|
||||
|
||||
nchars = strlen(line);
|
||||
|
||||
if (nchars == 0 || line[0] == '#'
|
||||
|| strspn(line, " \t\r\n") == nchars) {
|
||||
continue;
|
||||
}
|
||||
|
||||
str_trim(line);
|
||||
|
||||
if (!isspace(line[0])) {
|
||||
if (!usages_begin_page(line, &tmp_page)) {
|
||||
log_fatal("IDR_USAGES:%u: Invalid usage page",
|
||||
(unsigned int) line_no);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
cur_page = array_append(struct usage_page, &usages);
|
||||
memcpy(cur_page, &tmp_page, sizeof(tmp_page));
|
||||
} else {
|
||||
if (cur_page == NULL) {
|
||||
log_fatal("IDR_USAGES:%u: Usage before first page",
|
||||
(unsigned int) line_no);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (!usages_read_usage(line, cur_page)) {
|
||||
log_fatal("IDR_USAGES:%u: Invalid usage",
|
||||
(unsigned int) line_no);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool usages_begin_page(const char *line, struct usage_page *page)
|
||||
{
|
||||
int id;
|
||||
|
||||
if (sscanf(line, "%i", &id) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
page->id = (uint16_t) id;
|
||||
array_init(&page->usages);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool usages_read_usage(const char *line, struct usage_page *page)
|
||||
{
|
||||
struct usage *usage;
|
||||
int id;
|
||||
int offset;
|
||||
char c;
|
||||
|
||||
if (sscanf(line, " %c %n", &c, &offset) == 1 && c == '*') {
|
||||
str_cpy(page->wildcard, sizeof(page->wildcard), &line[offset]);
|
||||
page->wildcard[sizeof(page->wildcard) - 1] = '\0';
|
||||
|
||||
return true;
|
||||
} else if (sscanf(line, " %i %n", &id, &offset) == 1) {
|
||||
usage = array_append(struct usage, &page->usages);
|
||||
|
||||
usage->id = (uint16_t) id;
|
||||
str_cpy(usage->name, sizeof(usage->name), &line[offset]);
|
||||
usage->name[sizeof(usage->name) - 1] = '\0';
|
||||
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void usages_get(char *chars, size_t nchars, uint32_t usage_id)
|
||||
{
|
||||
const struct usage_page *page;
|
||||
const struct usage *usage;
|
||||
uint16_t hi;
|
||||
uint16_t lo;
|
||||
size_t i;
|
||||
size_t j;
|
||||
|
||||
hi = ((usage_id >> 16) & 0xFFFF);
|
||||
lo = ((usage_id >> 0) & 0xFFFF);
|
||||
|
||||
for (i = 0 ; i < usages.nitems ; i++) {
|
||||
page = array_item(struct usage_page, &usages, i);
|
||||
|
||||
if (page->id != hi) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (j = 0 ; j < page->usages.nitems ; j++) {
|
||||
usage = array_item(struct usage, &page->usages, j);
|
||||
|
||||
if (usage->id == lo) {
|
||||
str_cpy(chars, nchars, usage->name);
|
||||
chars[nchars - 1] = '\0';
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (page->wildcard[0]) {
|
||||
str_format(chars, nchars, page->wildcard, lo);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
str_format(chars, nchars, "%#08x", usage_id);
|
||||
}
|
||||
|
||||
void usages_fini(void)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0 ; i < usages.nitems ; i++) {
|
||||
array_fini(&array_item(struct usage_page, &usages, i)->usages);
|
||||
}
|
||||
|
||||
array_fini(&usages);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
#ifndef CONFIG_USAGES_H
|
||||
#define CONFIG_USAGES_H
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void usages_init(HINSTANCE inst);
|
||||
void usages_get(char *chars, uint32_t nchars, uint32_t usage);
|
||||
void usages_fini(void);
|
||||
|
||||
#endif
|
||||
Executable
+1244
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user