Bemanitools v5.26 release

This commit is contained in:
icex2
2019-09-27 22:36:50 +02:00
commit cbd7720349
718 changed files with 62731 additions and 0 deletions
+30
View File
@@ -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 \
+540
View File
@@ -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;
}
+530
View File
@@ -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);
}
+15
View File
@@ -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
+162
View File
@@ -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;
}
+16
View File
@@ -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
+127
View File
@@ -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;
}
+15
View File
@@ -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
+426
View File
@@ -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;
}
+14
View File
@@ -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>
+392
View File
@@ -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"
}
+489
View File
@@ -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;
}
+102
View File
@@ -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;
}
+11
View File
@@ -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
+513
View File
@@ -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;
}
+158
View File
@@ -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;
}
+245
View File
@@ -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
+391
View File
@@ -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);
+43
View File
@@ -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
+247
View File
@@ -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);
}
+27
View File
@@ -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
+118
View File
@@ -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);
}
+9
View File
@@ -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
+177
View File
@@ -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);
}
+12
View File
@@ -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
+1244
View File
File diff suppressed because it is too large Load Diff