mirror of
https://github.com/vanilla-wiiu/vanilla.git
synced 2026-10-28 09:43:51 +00:00
implement support for display brightness
commit 54e685ba9fef2b5fc1505ddc932e4fa3fe87ed68 Author: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Wed Aug 26 17:46:15 2026 -0700 improvements commitb442a51a71Author: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Wed Aug 26 14:49:31 2026 -0700 docker: add new build deps for android commit1e6370391eMerge:b21181c0681459Author: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Wed Aug 26 14:37:15 2026 -0700 Merge branch 'master' into brightness commitb21181c675Author: itsmattkc <34096995+itsmattkc@users.noreply.github.com> Date: Sun Aug 23 16:58:09 2026 -0700 update display brightness - initial implementation
This commit is contained in:
1 parent
7caf3a4d9e
commit
c809ff73e7
30 files changed
+322
-67
No files matched your search
@@ -2,6 +2,7 @@ package com.mattkc.vanilla;
|
||||
|
||||
import android.graphics.SurfaceTexture;
|
||||
import android.view.Surface;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
@@ -56,4 +57,18 @@ public class VanillaActivity extends SDLActivity {
|
||||
videoSurfaceTexture = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean setScreenBrightness(float brightness) {
|
||||
final VanillaActivity activity = (VanillaActivity) mSingleton;
|
||||
if (activity == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
activity.runOnUiThread(() -> {
|
||||
WindowManager.LayoutParams attributes = activity.getWindow().getAttributes();
|
||||
attributes.screenBrightness = Math.max(0.0f, Math.min(1.0f, brightness));
|
||||
activity.getWindow().setAttributes(attributes);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Listen for power button presses, in which case quit Vanilla (which should in turn reboot the Switch)
|
||||
|
||||
DEV=/dev/input/event0
|
||||
APP=vanilla
|
||||
|
||||
evtest "$DEV" 2>/dev/null | while read -r line; do
|
||||
case "$line" in
|
||||
*KEY_SLEEP*,\ value\ 1*)
|
||||
pid="$(pidof "$APP" | awk '{print $1}')"
|
||||
[ -n "$pid" ] && kill -TERM "$pid"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
@@ -1,16 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Listen for volume button presses, in which case increase/decrease volume in ALSA
|
||||
|
||||
DEV=/dev/input/event5
|
||||
|
||||
evtest "$DEV" 2>/dev/null | while read -r line; do
|
||||
case "$line" in
|
||||
*KEY_VOLUMEDOWN*,\ value\ 1*)
|
||||
amixer sset 'x Speaker' 5%- >/dev/null
|
||||
;;
|
||||
*KEY_VOLUMEUP*,\ value\ 1*)
|
||||
amixer sset 'x Speaker' 5%+ unmute >/dev/null
|
||||
;;
|
||||
esac
|
||||
done
|
||||
@@ -5,19 +5,6 @@ export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/lib/aarch64-linux-gnu/tegra:/usr/l
|
||||
export DISPLAY=:0
|
||||
export SDL_VIDEODRIVER=x11
|
||||
|
||||
# Listen for power button presses
|
||||
/usr/bin/vanilla-nx-power-btn &
|
||||
POWER_BTN_WATCHER_PID=$!
|
||||
/usr/bin/vanilla-nx-volume-btn &
|
||||
VOLUME_BTN_WATCHER_PID=$!
|
||||
|
||||
# Ensure watcher is closed
|
||||
cleanup() {
|
||||
kill "$POWER_BTN_WATCHER_PID" 2>/dev/null
|
||||
kill "$VOLUME_BTN_WATCHER_PID" 2>/dev/null
|
||||
}
|
||||
trap cleanup EXIT
|
||||
|
||||
# Start X
|
||||
X "$DISPLAY" -nolisten tcp vt1 &
|
||||
X_PID=$!
|
||||
|
||||
@@ -7,7 +7,7 @@ BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
|
||||
BR2_TARGET_GENERIC_ROOT_PASSWD="root"
|
||||
# BR2_TARGET_GENERIC_GETTY is not set
|
||||
# BR2_TARGET_GENERIC_REMOUNT_ROOTFS_RW is not set
|
||||
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/nx/rootfs/"
|
||||
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/nx/rootfs/ $(BR2_EXTERNAL_VANILLA_PATH)/rootfs/"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="$(BR2_EXTERNAL_VANILLA_PATH)/board/nx/post_build.sh"
|
||||
BR2_LINUX_KERNEL=y
|
||||
BR2_LINUX_KERNEL_IMAGEGZ=y
|
||||
|
||||
@@ -7,7 +7,7 @@ BR2_GLOBAL_PATCH_DIR="board/orangepi/orangepi-zero2w/patches $(BR2_EXTERNAL_VAN
|
||||
BR2_TARGET_GENERIC_ISSUE="Welcome to Orangepi Zero2W"
|
||||
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
|
||||
# BR2_TARGET_GENERIC_GETTY is not set
|
||||
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/orangepizero3/rootfs/"
|
||||
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/orangepizero3/rootfs/ $(BR2_EXTERNAL_VANILLA_PATH)/rootfs/"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="board/orangepi/common/post-build.sh $(BR2_EXTERNAL_VANILLA_PATH)/board/orangepizero3/post_build.sh"
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="support/scripts/genimage.sh"
|
||||
BR2_ROOTFS_POST_SCRIPT_ARGS="-c $(BINARIES_DIR)/genimage.cfg"
|
||||
|
||||
@@ -8,7 +8,7 @@ BR2_TARGET_GENERIC_ISSUE="Welcome to Orangepi Zero3"
|
||||
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
|
||||
# BR2_TARGET_GENERIC_GETTY is not set
|
||||
BR2_SYSTEM_DHCP="eth0"
|
||||
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/orangepizero3/rootfs/"
|
||||
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/orangepizero3/rootfs/ $(BR2_EXTERNAL_VANILLA_PATH)/rootfs/"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="board/orangepi/common/post-build.sh $(BR2_EXTERNAL_VANILLA_PATH)/board/orangepizero3/post_build.sh"
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="support/scripts/genimage.sh"
|
||||
BR2_ROOTFS_POST_SCRIPT_ARGS="-c $(BINARIES_DIR)/genimage.cfg"
|
||||
|
||||
@@ -5,7 +5,7 @@ BR2_GLOBAL_PATCH_DIR="board/raspberrypi/patches"
|
||||
BR2_DOWNLOAD_FORCE_CHECK_HASHES=y
|
||||
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
|
||||
# BR2_TARGET_GENERIC_GETTY is not set
|
||||
#BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/raspberrypi/rootfs"
|
||||
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/rootfs/"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="board/raspberrypi0w/post-build.sh $(BR2_EXTERNAL_VANILLA_PATH)/board/raspberrypi/post_build.sh"
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="board/raspberrypi0w/post-image.sh"
|
||||
BR2_LINUX_KERNEL=y
|
||||
|
||||
@@ -6,7 +6,7 @@ BR2_GLOBAL_PATCH_DIR="board/raspberrypi/patches"
|
||||
BR2_DOWNLOAD_FORCE_CHECK_HASHES=y
|
||||
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
|
||||
# BR2_TARGET_GENERIC_GETTY is not set
|
||||
#BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/board/raspberrypi/rootfs"
|
||||
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_VANILLA_PATH)/rootfs/"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="board/raspberrypi/post-build.sh $(BR2_EXTERNAL_VANILLA_PATH)/board/raspberrypi/post_build.sh"
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="board/raspberrypi/post-image.sh"
|
||||
BR2_LINUX_KERNEL=y
|
||||
|
||||
Executable
+13
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
case "$1" in
|
||||
up)
|
||||
exec amixer -q sset 'x Speaker' 5%+ unmute
|
||||
;;
|
||||
down)
|
||||
exec amixer -q sset 'x Speaker' 5%-
|
||||
;;
|
||||
*)
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
@@ -2,7 +2,7 @@ FROM docker.io/ubuntu:24.04@sha256:33ceb71981b602c1a7443a53469e4dba065f7503eab30
|
||||
|
||||
# Install build dependencies
|
||||
RUN apt update && \
|
||||
apt -y install wget unzip git openjdk-17-jdk make && \
|
||||
apt -y install wget unzip git openjdk-17-jdk make autoconf automake libtool pkg-config && \
|
||||
apt-get clean && \
|
||||
apt-get autoremove --yes && \
|
||||
rm -rf /var/lib/{apt,dpkg,cache,log}/
|
||||
|
||||
@@ -309,6 +309,10 @@ if (ANDROID)
|
||||
endif()
|
||||
|
||||
if (LINUX)
|
||||
list(APPEND VANILLA_GUI_SRC
|
||||
ui/ui_sdl_linux.c
|
||||
)
|
||||
|
||||
# Link with DRM if available
|
||||
option(VANILLA_BUILD_USE_DRM "Enable DRM video output" ON)
|
||||
if (VANILLA_BUILD_USE_DRM)
|
||||
|
||||
@@ -93,6 +93,9 @@ void vpi_config_save()
|
||||
sprintf(buf, "%i", vpi_config.force_software_decode);
|
||||
xmlTextWriterWriteElement(writer, BAD_CAST "swdec", BAD_CAST buf);
|
||||
|
||||
sprintf(buf, "%f", vpi_config.screen_brightness);
|
||||
xmlTextWriterWriteElement(writer, BAD_CAST "brightness", BAD_CAST buf);
|
||||
|
||||
xmlTextWriterStartElement(writer, BAD_CAST "controls");
|
||||
if (vpi_config.keymap) {
|
||||
xmlTextWriterStartElement(writer, BAD_CAST "keys");
|
||||
@@ -184,6 +187,7 @@ void vpi_config_init()
|
||||
vpi_config_reset_default_controls_internal();
|
||||
vpi_config.cursor_in_fullscreen = 0;
|
||||
vpi_config.autoconnect = -1;
|
||||
vpi_config.screen_brightness = 0.5f;
|
||||
|
||||
// Load from file
|
||||
char config_fn[1024];
|
||||
@@ -250,6 +254,8 @@ void vpi_config_init()
|
||||
vpi_config.fullscreen = atoi((const char *) child->children->content);
|
||||
} else if (!strcmp((const char *) child->name, "swdec")) {
|
||||
vpi_config.force_software_decode = atoi((const char *) child->children->content);
|
||||
} else if (!strcmp((const char *) child->name, "brightness")) {
|
||||
vpi_config.screen_brightness = atof((const char *) child->children->content);
|
||||
} else if (!strcmp((const char *) child->name, "controls")) {
|
||||
xmlNodePtr section = child->children;
|
||||
while(section){
|
||||
|
||||
@@ -33,6 +33,7 @@ typedef struct {
|
||||
int fast_drm;
|
||||
int force_software_decode;
|
||||
int autoconnect;
|
||||
float screen_brightness;
|
||||
} vpi_config_t;
|
||||
|
||||
extern vpi_config_t vpi_config;
|
||||
|
||||
@@ -97,6 +97,14 @@ int SDL_main(int argc, const char **argv)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#ifndef ANDROID
|
||||
// On Linux/Buildroot platforms like Raspberry Pi and Nintendo Switch, it
|
||||
// is desirable for the brightness to be restored from config. On Android
|
||||
// though, the brightness will be set externally so changing it here is
|
||||
// probably not desirable.
|
||||
vui_brightness_set(vui, vpi_config.screen_brightness);
|
||||
#endif
|
||||
|
||||
vpi_menu_init(vui);
|
||||
|
||||
while (vui_update_sdl(vui)) {
|
||||
|
||||
@@ -13,6 +13,20 @@
|
||||
#include "menu_main.h"
|
||||
#include "platform.h"
|
||||
|
||||
#if defined(__linux__) && !defined(ANDROID) && !defined(__ANDROID__)
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
// Calling system() is synchronous and causes a noticeable pause during
|
||||
// gameplay. This allows us to thunk from a separate detached thread so it
|
||||
// doesn't interrupt the main thread.
|
||||
static void *run_volume_helper(void *command)
|
||||
{
|
||||
(void) system((const char *) command);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
void vpi_mic_callback(void *userdata, const uint8_t *data, size_t len)
|
||||
{
|
||||
vanilla_send_audio(data, len);
|
||||
@@ -80,6 +94,31 @@ void vpi_menu_action(vui_context_t *vui, vpi_extra_action_t action)
|
||||
vpi_config.fullscreen = !vpi_config.fullscreen;
|
||||
vpi_config_save();
|
||||
vui_set_fullscreen(vui, vpi_config.fullscreen);
|
||||
break;
|
||||
}
|
||||
case VPI_ACTION_VOLUME_UP:
|
||||
case VPI_ACTION_VOLUME_DOWN:
|
||||
{
|
||||
#if defined(__linux__) && !defined(ANDROID) && !defined(__ANDROID__)
|
||||
// On some platforms (specifically our Buildroot platforms like the
|
||||
// Raspberry Pi and Nintendo Switch), there's no built-in handler for
|
||||
// the volume keys. So here we handle them ourselves.
|
||||
const char *helper = "/usr/libexec/vanilla-volume";
|
||||
if (access(helper, X_OK) == 0) {
|
||||
const char *command = action == VPI_ACTION_VOLUME_UP
|
||||
? "/usr/libexec/vanilla-volume up"
|
||||
: "/usr/libexec/vanilla-volume down";
|
||||
pthread_t thread;
|
||||
int error = pthread_create(&thread, NULL, run_volume_helper, (void *) command);
|
||||
if (error == 0) {
|
||||
error = pthread_detach(thread);
|
||||
}
|
||||
if (error != 0) {
|
||||
vpilog("Failed to start volume helper thread: %s\n", strerror(error));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@ typedef enum {
|
||||
VPI_ACTION_TOGGLE_RECORDING,
|
||||
VPI_ACTION_DISCONNECT,
|
||||
VPI_ACTION_TOGGLE_FULLSCREEN,
|
||||
VPI_ACTION_VOLUME_UP,
|
||||
VPI_ACTION_VOLUME_DOWN
|
||||
} vpi_extra_action_t;
|
||||
|
||||
void vpi_menu_init(vui_context_t *vui);
|
||||
|
||||
@@ -1088,6 +1088,21 @@ void *vpi_event_loop(void *arg)
|
||||
case VANILLA_EVENT_MIC:
|
||||
vui_mic_enabled_set(vui, event.data[0]);
|
||||
break;
|
||||
case VANILLA_EVENT_BRIGHTNESS:
|
||||
{
|
||||
// Clamp to valid values from console
|
||||
uint8_t value = CLAMP(event.data[0], 1, 5);
|
||||
|
||||
// Normalize to 0.0 - 1.0
|
||||
// float b = value / 5.0f;
|
||||
float b = (value - 1) / 4.0f;
|
||||
if (b < 0.01f) b = 0.01f;
|
||||
|
||||
vpi_config.screen_brightness = b;
|
||||
vpi_config_save();
|
||||
vui_brightness_set(vui, b);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
vanilla_free_event(&event);
|
||||
|
||||
@@ -1041,3 +1041,10 @@ void vui_mic_callback_set(vui_context_t *ctx, vui_mic_callback_t callback, void
|
||||
ctx->mic_callback = callback;
|
||||
ctx->mic_callback_data = userdata;
|
||||
}
|
||||
|
||||
void vui_brightness_set(vui_context_t *ctx, float brightness)
|
||||
{
|
||||
if (ctx->brightness_set_handler) {
|
||||
ctx->brightness_set_handler(ctx, brightness, ctx->brightness_set_handler_data);
|
||||
}
|
||||
}
|
||||
@@ -182,4 +182,9 @@ vui_power_state_t vui_power_state_get(vui_context_t *ctx, int *percent);
|
||||
void vui_mic_enabled_set(vui_context_t *ctx, int enabled);
|
||||
void vui_mic_callback_set(vui_context_t *ctx, vui_mic_callback_t callback, void *userdata);
|
||||
|
||||
/**
|
||||
* Miscellaneous functions
|
||||
*/
|
||||
void vui_brightness_set(vui_context_t *ctx, float brightness); // Expects brightness between 0.0f and 1.0f
|
||||
|
||||
#endif // VANILLA_PI_UI_H
|
||||
@@ -104,6 +104,7 @@ typedef int (*vui_font_height_handler_t)(vui_font_size_t size, void *userdata);
|
||||
typedef void (*vui_text_open_handler_t)(vui_context_t *ctx, int textedit, int open, void *userdata);
|
||||
typedef vui_power_state_t (*vui_power_state_handler_t)(vui_context_t *ctx, int *percent);
|
||||
typedef void (*vui_audio_enabled_handler_t)(vui_context_t *ctx, int enabled, void *userdata);
|
||||
typedef void (*vui_brightness_set_handler_t)(vui_context_t *ctx, float value, void *userdata);
|
||||
|
||||
typedef struct vui_context_t {
|
||||
void *platform_data;
|
||||
@@ -155,6 +156,8 @@ typedef struct vui_context_t {
|
||||
void *audio_enabled_handler_data;
|
||||
vui_bool_callback_t fullscreen_enabled_handler;
|
||||
void *fullscreen_enabled_handler_data;
|
||||
vui_brightness_set_handler_t brightness_set_handler;
|
||||
void *brightness_set_handler_data;
|
||||
|
||||
int default_button_map[VPI_CONFIG_BUTTONMAP_SIZE];
|
||||
int default_axis_map[VPI_CONFIG_AXISMAP_SIZE];
|
||||
|
||||
+33
-1
@@ -49,6 +49,12 @@
|
||||
#include "platform_nx_imu.h"
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID) || defined(__ANDROID__)
|
||||
// TODO
|
||||
#elif defined(__linux__)
|
||||
#include "ui_sdl_linux.h"
|
||||
#endif
|
||||
|
||||
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||
#define PW_CHAR_SIZE 20
|
||||
#define PW_CHAR_PAD 2
|
||||
@@ -187,6 +193,10 @@ void init_gamepad(vui_context_t *ctx)
|
||||
ctx->default_key_map[SDL_SCANCODE_F12] = VPI_ACTION_SCREENSHOT;
|
||||
ctx->default_key_map[SDL_SCANCODE_F11] = VPI_ACTION_TOGGLE_FULLSCREEN;
|
||||
ctx->default_key_map[SDL_SCANCODE_ESCAPE] = VPI_ACTION_DISCONNECT;
|
||||
|
||||
ctx->default_key_map[SDL_SCANCODE_SLEEP] = VPI_ACTION_DISCONNECT; // Nintendo Switch power button
|
||||
ctx->default_key_map[SDL_SCANCODE_VOLUMEUP] = VPI_ACTION_VOLUME_UP;
|
||||
ctx->default_key_map[SDL_SCANCODE_VOLUMEDOWN] = VPI_ACTION_VOLUME_DOWN;
|
||||
}
|
||||
|
||||
void find_valid_controller(vui_sdl_context_t *sdl_ctx)
|
||||
@@ -354,6 +364,26 @@ void vui_sdl_fullscreen_enabled_handler(vui_context_t *ctx, int enabled, void *u
|
||||
SDL_ShowCursor(vpi_config.cursor_in_fullscreen || !enabled);
|
||||
}
|
||||
|
||||
void vui_sdl_brightness_set_handler(vui_context_t *ctx, float brightness, void *userdata)
|
||||
{
|
||||
vui_sdl_context_t *sdl_ctx = (vui_sdl_context_t *) ctx->platform_data;
|
||||
|
||||
vpilog("SETTING BRIGHTNESS TO %.1f\n", brightness);
|
||||
|
||||
#if defined(ANDROID) || defined(__ANDROID__)
|
||||
if (vui_sdl_android_set_brightness(brightness) == 0) {
|
||||
return;
|
||||
}
|
||||
#elif defined(__linux__)
|
||||
if (vui_sdl_linux_set_brightness(brightness) == 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Fallback
|
||||
SDL_SetWindowBrightness(sdl_ctx->window, brightness);
|
||||
}
|
||||
|
||||
void vui_sdl_get_key_mapping_handler(vui_context_t *ctx, int vanilla_btn, void *userdata)
|
||||
{
|
||||
|
||||
@@ -537,7 +567,7 @@ int vui_sdl_event_thread(void *data)
|
||||
break;
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
if (sdl_ctx->controller && ev.cdevice.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(sdl_ctx->controller))) {
|
||||
if (sdl_ctx->controller && ev.cdevice.which == SDL_JoystickInstanceID(SDL_GameControllerGetJoystick(sdl_ctx->controller))) {
|
||||
int btn_idx = ev.cbutton.button;
|
||||
int vanilla_btn;
|
||||
|
||||
@@ -880,6 +910,8 @@ int vui_init_sdl(vui_context_t *ctx, int fullscreen)
|
||||
|
||||
ctx->fullscreen_enabled_handler = vui_sdl_fullscreen_enabled_handler;
|
||||
|
||||
ctx->brightness_set_handler = vui_sdl_brightness_set_handler;
|
||||
|
||||
if (TTF_Init()) {
|
||||
vpilog("Failed to TTF_Init\n");
|
||||
return -1;
|
||||
|
||||
+20
-1
@@ -12,6 +12,7 @@ static jobject video_surface;
|
||||
static jmethodID create_surface_method;
|
||||
static jmethodID update_texture_method;
|
||||
static jmethodID destroy_surface_method;
|
||||
static jmethodID set_brightness_method;
|
||||
|
||||
static int handle_jni_exception(JNIEnv *env, const char *operation)
|
||||
{
|
||||
@@ -53,7 +54,8 @@ static int init_jni(JNIEnv *env)
|
||||
create_surface_method = (*env)->GetStaticMethodID(env, video_class, "createVideoSurface", "(III)Landroid/view/Surface;");
|
||||
update_texture_method = (*env)->GetStaticMethodID(env, video_class, "updateVideoSurfaceTexture", "()[F");
|
||||
destroy_surface_method = (*env)->GetStaticMethodID(env, video_class, "destroyVideoSurface", "()V");
|
||||
if (!create_surface_method || !update_texture_method || !destroy_surface_method ||
|
||||
set_brightness_method = (*env)->GetStaticMethodID(env, video_class, "setScreenBrightness", "(F)Z");
|
||||
if (!create_surface_method || !update_texture_method || !destroy_surface_method || !set_brightness_method ||
|
||||
handle_jni_exception(env, "looking up video surface methods") < 0) {
|
||||
(*env)->DeleteGlobalRef(env, video_class);
|
||||
video_class = NULL;
|
||||
@@ -69,6 +71,7 @@ static int init_jni(JNIEnv *env)
|
||||
create_surface_method = NULL;
|
||||
update_texture_method = NULL;
|
||||
destroy_surface_method = NULL;
|
||||
set_brightness_method = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -144,6 +147,21 @@ void *vui_sdl_android_get_video_surface(void)
|
||||
return video_surface;
|
||||
}
|
||||
|
||||
int vui_sdl_android_set_brightness(float brightness)
|
||||
{
|
||||
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
|
||||
if (!env || init_jni(env) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
jboolean dispatched = (*env)->CallStaticBooleanMethod(env, video_class, set_brightness_method,
|
||||
(jfloat) brightness);
|
||||
if (handle_jni_exception(env, "setting screen brightness") < 0) {
|
||||
return -1;
|
||||
}
|
||||
return dispatched ? 0 : -1;
|
||||
}
|
||||
|
||||
int vui_sdl_android_update_video_texture(float transform[16])
|
||||
{
|
||||
JNIEnv *env = (JNIEnv *) SDL_AndroidGetJNIEnv();
|
||||
@@ -192,4 +210,5 @@ void vui_sdl_android_destroy_video_texture(void)
|
||||
create_surface_method = NULL;
|
||||
update_texture_method = NULL;
|
||||
destroy_surface_method = NULL;
|
||||
set_brightness_method = NULL;
|
||||
}
|
||||
@@ -8,5 +8,6 @@ int vui_sdl_android_create_video_texture(SDL_Renderer *renderer, int width,
|
||||
void *vui_sdl_android_get_video_surface(void);
|
||||
int vui_sdl_android_update_video_texture(float transform[16]);
|
||||
void vui_sdl_android_destroy_video_texture(void);
|
||||
int vui_sdl_android_set_brightness(float brightness);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
#include "ui_sdl_linux.h"
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ui_util.h"
|
||||
|
||||
#define VUI_LINUX_BACKLIGHT_ROOT "/sys/class/backlight"
|
||||
#define VUI_LINUX_BACKLIGHT_DEFAULT "backlight"
|
||||
#define VUI_LINUX_BACKLIGHT_PATH_SIZE 4096
|
||||
|
||||
static int vui_sdl_linux_set_backlight_device(const char *device, float brightness)
|
||||
{
|
||||
char path[VUI_LINUX_BACKLIGHT_PATH_SIZE];
|
||||
unsigned int max_brightness;
|
||||
unsigned int value;
|
||||
int path_length;
|
||||
int write_failed;
|
||||
int close_failed;
|
||||
FILE *file;
|
||||
|
||||
if (!isfinite(brightness)) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
brightness = CLAMP(brightness, 0.0f, 1.0f);
|
||||
|
||||
// Attempt to read max_brightness information
|
||||
path_length = snprintf(path, sizeof(path), "%s/%s/max_brightness", VUI_LINUX_BACKLIGHT_ROOT, device);
|
||||
if (path_length < 0 || path_length >= (int) sizeof(path)) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
file = fopen(path, "r");
|
||||
if (!file) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fscanf(file, "%u", &max_brightness) != 1 || !max_brightness) {
|
||||
fclose(file);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
fclose(file);
|
||||
|
||||
// Now that we have max_brightness, attempt to set actual brightness to a percentage of max brightness
|
||||
value = lroundf(brightness * max_brightness);
|
||||
|
||||
path_length = snprintf(path, sizeof(path), "%s/%s/brightness", VUI_LINUX_BACKLIGHT_ROOT, device);
|
||||
if (path_length < 0 || path_length >= (int) sizeof(path)) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
|
||||
file = fopen(path, "w");
|
||||
if (!file) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
write_failed = fprintf(file, "%u\n", value) < 0;
|
||||
close_failed = fclose(file) != 0;
|
||||
if (write_failed || close_failed) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vui_sdl_linux_set_brightness(float brightness)
|
||||
{
|
||||
DIR *directory;
|
||||
struct dirent *entry;
|
||||
|
||||
// See if "backlight" device exists (should exist on Nintendo Switch)
|
||||
if (access(VUI_LINUX_BACKLIGHT_ROOT "/" VUI_LINUX_BACKLIGHT_DEFAULT, F_OK) == 0) {
|
||||
return vui_sdl_linux_set_backlight_device(VUI_LINUX_BACKLIGHT_DEFAULT, brightness);
|
||||
}
|
||||
|
||||
// Otherwise, iterate over directory to find next best device to set brightness on
|
||||
directory = opendir(VUI_LINUX_BACKLIGHT_ROOT);
|
||||
if (!directory) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
while ((entry = readdir(directory))) {
|
||||
if (entry->d_name[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vui_sdl_linux_set_backlight_device(entry->d_name, brightness) == 0) {
|
||||
closedir(directory);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
closedir(directory);
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
#ifndef VANILLA_PI_UI_SDL_LINUX_H
|
||||
#define VANILLA_PI_UI_SDL_LINUX_H
|
||||
|
||||
int vui_sdl_linux_set_brightness(float brightness);
|
||||
|
||||
#endif // VANILLA_PI_UI_SDL_LINUX_H
|
||||
@@ -9,6 +9,8 @@ void vui_strncpy(char *dst, const char *src, size_t max_dst_size);
|
||||
size_t vui_utf8_cp_len(const char *s);
|
||||
char *vui_utf8_advance(char *s);
|
||||
|
||||
#define CLAMP(x, low, high) (((x) < (low)) ? (low) : ((x) > (high)) ? (high) : (x))
|
||||
|
||||
static inline int intmin(int a, int b) { return a < b ? a : b; }
|
||||
static inline int intmax(int a, int b) { return a > b ? a : b; }
|
||||
static inline int64_t int64min(int64_t a, int64_t b) { return a < b ? a : b; }
|
||||
|
||||
+31
-5
@@ -60,7 +60,7 @@ void send_generic_response(int skt, CmdHeader *response)
|
||||
void handle_generic_packet(gamepad_context_t *info, int skt, GenericPacket *request)
|
||||
{
|
||||
GenericCmdHeader *gen_cmd = &request->generic_cmd_header;
|
||||
vanilla_log("magic: %x, flags: %x, service ID: %u, method ID: %u", gen_cmd->magic_0x7E, gen_cmd->flags, gen_cmd->service_id, gen_cmd->method_id);
|
||||
// vanilla_log("magic: %x, flags: %x, service ID: %u, method ID: %u", gen_cmd->magic_0x7E, gen_cmd->flags, gen_cmd->service_id, gen_cmd->method_id);
|
||||
|
||||
// Prepare response
|
||||
GenericPacket response;
|
||||
@@ -170,13 +170,39 @@ void handle_generic_packet(gamepad_context_t *info, int skt, GenericPacket *requ
|
||||
}
|
||||
case METHOD_ID_PERIPHERAL_UPDATE_EEPROM:
|
||||
{
|
||||
vanilla_log("5,12 - index: %u, length: %u", response.payload[0], response.payload[1]);
|
||||
response.generic_cmd_header.error_code = 0;
|
||||
uint8_t index = request->payload[0];
|
||||
uint8_t length = request->payload[1];
|
||||
|
||||
vanilla_log("5,12 - index: %u, length: %u", index, length);
|
||||
|
||||
uint16_t our_crc = crc16(request->payload + 2, length - 2);
|
||||
uint16_t their_crc = le16toh(*(uint16_t *)(request->payload + 2 + length - 2));
|
||||
|
||||
if (our_crc != their_crc) {
|
||||
// TODO: Report some kind of error to the console?
|
||||
} else {
|
||||
// Update our EEPROM
|
||||
switch (index) {
|
||||
case 0x10:
|
||||
{
|
||||
// Console wants to change our brightness
|
||||
// vanilla_log("Change brightness to %x", request->payload[2]);
|
||||
uint8_t b = request->payload[2];
|
||||
push_event(info->event_loop, VANILLA_EVENT_BRIGHTNESS, &b, sizeof(b));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
vanilla_log("Console attempted write to unknown EEPROM offset: 0x%x", index);
|
||||
}
|
||||
|
||||
// Report success
|
||||
response.generic_cmd_header.error_code = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case METHOD_ID_PERIPHERAL_SET_REMOCON:
|
||||
{
|
||||
vanilla_log("5,24 - str1: %s, str2: %s", response.payload, response.payload + 5);
|
||||
vanilla_log("5,24 - str1: %s, str2: %s", request->payload, request->payload + 5);
|
||||
response.generic_cmd_header.error_code = 0;
|
||||
break;
|
||||
}
|
||||
@@ -227,7 +253,7 @@ void handle_time_packet(int skt, TimePacket *request)
|
||||
|
||||
void handle_command_packet(gamepad_context_t *info, int skt, CmdHeader *request)
|
||||
{
|
||||
vanilla_log("packet_type: %u, query_type: %u, payload_size: 0x%X", request->packet_type, request->query_type, request->payload_size);
|
||||
// vanilla_log("packet_type: %u, query_type: %u, payload_size: 0x%X", request->packet_type, request->query_type, request->payload_size);
|
||||
switch (request->packet_type)
|
||||
{
|
||||
case PACKET_TYPE_REQUEST:
|
||||
|
||||
@@ -20,15 +20,6 @@
|
||||
#include "vanilla.h"
|
||||
#include "util.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Windows has no htobe32, and is always virtually little-endiam
|
||||
#define htobe32(x) htonl(x)
|
||||
#elif defined(__APPLE__)
|
||||
// macOS has no htobe32
|
||||
#include <libkern/OSByteOrder.h>
|
||||
#define htobe32(x) OSSwapHostToBigInt32(x)
|
||||
#endif // __APPLE__
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned magic : 4;
|
||||
|
||||
+2
-1
@@ -74,7 +74,8 @@ enum VanillaEvent
|
||||
VANILLA_EVENT_VIBRATE,
|
||||
VANILLA_EVENT_SYNC,
|
||||
VANILLA_EVENT_ERROR,
|
||||
VANILLA_EVENT_MIC
|
||||
VANILLA_EVENT_MIC,
|
||||
VANILLA_EVENT_BRIGHTNESS
|
||||
};
|
||||
|
||||
enum VanillaRegion
|
||||
|
||||
Reference in new issue
Block a user