Merge branch 'master' of https://github.com/libretro/RetroArch into discord_improvements
This commit is contained in:
commit
fd7d8d9424
|
@ -1066,7 +1066,7 @@ static void command_event_init_controllers(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (set_controller && i < info->ports.size)
|
if (set_controller && info && i < info->ports.size)
|
||||||
{
|
{
|
||||||
pad.device = device;
|
pad.device = device;
|
||||||
pad.port = i;
|
pad.port = i;
|
||||||
|
|
|
@ -1069,7 +1069,7 @@ bool config_overlay_enable_default(void)
|
||||||
static struct config_array_setting *populate_settings_array(settings_t *settings, int *size)
|
static struct config_array_setting *populate_settings_array(settings_t *settings, int *size)
|
||||||
{
|
{
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
struct config_array_setting *tmp = (struct config_array_setting*)malloc((*size + 1) * sizeof(struct config_array_setting));
|
struct config_array_setting *tmp = (struct config_array_setting*)calloc(1, (*size + 1) * sizeof(struct config_array_setting));
|
||||||
|
|
||||||
/* Arrays */
|
/* Arrays */
|
||||||
SETTING_ARRAY("playlist_names", settings->arrays.playlist_names, false, NULL, true);
|
SETTING_ARRAY("playlist_names", settings->arrays.playlist_names, false, NULL, true);
|
||||||
|
@ -1112,7 +1112,7 @@ static struct config_path_setting *populate_settings_path(settings_t *settings,
|
||||||
{
|
{
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
global_t *global = global_get_ptr();
|
global_t *global = global_get_ptr();
|
||||||
struct config_path_setting *tmp = (struct config_path_setting*)malloc((*size + 1) * sizeof(struct config_path_setting));
|
struct config_path_setting *tmp = (struct config_path_setting*)calloc(1, (*size + 1) * sizeof(struct config_path_setting));
|
||||||
|
|
||||||
/* Paths */
|
/* Paths */
|
||||||
#ifdef HAVE_XMB
|
#ifdef HAVE_XMB
|
||||||
|
@ -1308,7 +1308,7 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
|
||||||
SETTING_BOOL("video_vsync", &settings->bools.video_vsync, true, vsync, false);
|
SETTING_BOOL("video_vsync", &settings->bools.video_vsync, true, vsync, false);
|
||||||
SETTING_BOOL("video_hard_sync", &settings->bools.video_hard_sync, true, hard_sync, false);
|
SETTING_BOOL("video_hard_sync", &settings->bools.video_hard_sync, true, hard_sync, false);
|
||||||
SETTING_BOOL("video_black_frame_insertion", &settings->bools.video_black_frame_insertion, true, black_frame_insertion, false);
|
SETTING_BOOL("video_black_frame_insertion", &settings->bools.video_black_frame_insertion, true, black_frame_insertion, false);
|
||||||
SETTING_BOOL("crt_switch_resolution", &settings->bools.crt_switch_resolution, true, crt_switch_resolution, false);
|
SETTING_BOOL("crt_switch_resolution", &settings->bools.crt_switch_resolution, true, crt_switch_resolution, false);
|
||||||
SETTING_BOOL("video_disable_composition", &settings->bools.video_disable_composition, true, disable_composition, false);
|
SETTING_BOOL("video_disable_composition", &settings->bools.video_disable_composition, true, disable_composition, false);
|
||||||
SETTING_BOOL("pause_nonactive", &settings->bools.pause_nonactive, true, pause_nonactive, false);
|
SETTING_BOOL("pause_nonactive", &settings->bools.pause_nonactive, true, pause_nonactive, false);
|
||||||
SETTING_BOOL("video_gpu_screenshot", &settings->bools.video_gpu_screenshot, true, gpu_screenshot, false);
|
SETTING_BOOL("video_gpu_screenshot", &settings->bools.video_gpu_screenshot, true, gpu_screenshot, false);
|
||||||
|
@ -3027,6 +3027,8 @@ end:
|
||||||
free(array_settings);
|
free(array_settings);
|
||||||
if (path_settings)
|
if (path_settings)
|
||||||
free(path_settings);
|
free(path_settings);
|
||||||
|
if (size_settings)
|
||||||
|
free(size_settings);
|
||||||
free(tmp_str);
|
free(tmp_str);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -4431,7 +4433,7 @@ bool config_save_overrides(int override_type)
|
||||||
for (i = 0; i < (unsigned)path_settings_size; i++)
|
for (i = 0; i < (unsigned)path_settings_size; i++)
|
||||||
{
|
{
|
||||||
|
|
||||||
/* blacklist video_shader, better handled by shader presets*/
|
/* blacklist video_shader, better handled by shader presets*/
|
||||||
/* to-do: add setting to control blacklisting */
|
/* to-do: add setting to control blacklisting */
|
||||||
if (string_is_equal(path_settings[i].ident, "video_shader"))
|
if (string_is_equal(path_settings[i].ident, "video_shader"))
|
||||||
continue;
|
continue;
|
||||||
|
@ -4536,6 +4538,8 @@ bool config_save_overrides(int override_type)
|
||||||
free(path_settings);
|
free(path_settings);
|
||||||
if (path_overrides)
|
if (path_overrides)
|
||||||
free(path_overrides);
|
free(path_overrides);
|
||||||
|
if (size_overrides)
|
||||||
|
free(size_overrides);
|
||||||
free(settings);
|
free(settings);
|
||||||
free(config_directory);
|
free(config_directory);
|
||||||
free(override_directory);
|
free(override_directory);
|
||||||
|
|
|
@ -478,6 +478,36 @@ database_info_list_t *database_info_list_new(
|
||||||
|
|
||||||
if (!new_ptr)
|
if (!new_ptr)
|
||||||
{
|
{
|
||||||
|
if (db_info.bbfc_rating)
|
||||||
|
free(db_info.bbfc_rating);
|
||||||
|
if (db_info.cero_rating)
|
||||||
|
free(db_info.cero_rating);
|
||||||
|
if (db_info.description)
|
||||||
|
free(db_info.description);
|
||||||
|
if (db_info.edge_magazine_review)
|
||||||
|
free(db_info.edge_magazine_review);
|
||||||
|
if (db_info.elspa_rating)
|
||||||
|
free(db_info.elspa_rating);
|
||||||
|
if (db_info.enhancement_hw)
|
||||||
|
free(db_info.enhancement_hw);
|
||||||
|
if (db_info.esrb_rating)
|
||||||
|
free(db_info.esrb_rating);
|
||||||
|
if (db_info.franchise)
|
||||||
|
free(db_info.franchise);
|
||||||
|
if (db_info.genre)
|
||||||
|
free(db_info.genre);
|
||||||
|
if (db_info.name)
|
||||||
|
free(db_info.name);
|
||||||
|
if (db_info.origin)
|
||||||
|
free(db_info.origin);
|
||||||
|
if (db_info.pegi_rating)
|
||||||
|
free(db_info.pegi_rating);
|
||||||
|
if (db_info.publisher)
|
||||||
|
free(db_info.publisher);
|
||||||
|
if (db_info.rom_name)
|
||||||
|
free(db_info.rom_name);
|
||||||
|
if (db_info.serial)
|
||||||
|
free(db_info.serial);
|
||||||
database_info_list_free(database_info_list);
|
database_info_list_free(database_info_list);
|
||||||
free(database_info);
|
free(database_info);
|
||||||
free(database_info_list);
|
free(database_info_list);
|
||||||
|
|
|
@ -63,12 +63,14 @@ void create_gdi_context(HWND hwnd, bool *quit);
|
||||||
|
|
||||||
bool gdi_has_menu_frame(void);
|
bool gdi_has_menu_frame(void);
|
||||||
|
|
||||||
|
#if !defined(__WINRT__)
|
||||||
bool win32_window_init(WNDCLASSEX *wndclass, bool fullscreen, const char *class_name);
|
bool win32_window_init(WNDCLASSEX *wndclass, bool fullscreen, const char *class_name);
|
||||||
|
|
||||||
void win32_set_style(MONITORINFOEX *current_mon, HMONITOR *hm_to_use,
|
void win32_set_style(MONITORINFOEX *current_mon, HMONITOR *hm_to_use,
|
||||||
unsigned *width, unsigned *height, bool fullscreen, bool windowed_full,
|
unsigned *width, unsigned *height, bool fullscreen, bool windowed_full,
|
||||||
RECT *rect, RECT *mon_rect, DWORD *style);
|
RECT *rect, RECT *mon_rect, DWORD *style);
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
void win32_monitor_from_window(void);
|
void win32_monitor_from_window(void);
|
||||||
|
|
||||||
|
|
|
@ -380,7 +380,7 @@ static bool gl_shader_init(gl_t *gl, const gfx_ctx_driver_t *ctx_driver,
|
||||||
video_shader_ctx_init_t init_data;
|
video_shader_ctx_init_t init_data;
|
||||||
enum rarch_shader_type type = DEFAULT_SHADER_TYPE;
|
enum rarch_shader_type type = DEFAULT_SHADER_TYPE;
|
||||||
const char *shader_path = retroarch_get_shader_preset();
|
const char *shader_path = retroarch_get_shader_preset();
|
||||||
|
|
||||||
if (shader_path)
|
if (shader_path)
|
||||||
{
|
{
|
||||||
type = video_shader_parse_type(shader_path,
|
type = video_shader_parse_type(shader_path,
|
||||||
|
@ -839,7 +839,7 @@ static void gl_show_mouse(void *data, bool state)
|
||||||
|
|
||||||
static struct video_shader *gl_get_current_shader(void *data)
|
static struct video_shader *gl_get_current_shader(void *data)
|
||||||
{
|
{
|
||||||
video_shader_ctx_t shader_info;
|
video_shader_ctx_t shader_info = {0};
|
||||||
|
|
||||||
video_shader_driver_direct_get_current_shader(&shader_info);
|
video_shader_driver_direct_get_current_shader(&shader_info);
|
||||||
|
|
||||||
|
@ -1798,9 +1798,9 @@ static void *gl_init(const video_info_t *video,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!renderchain_gl_init_first(&gl->renderchain_driver,
|
if (!renderchain_gl_init_first(&gl->renderchain_driver,
|
||||||
&gl->renderchain_data))
|
&gl->renderchain_data))
|
||||||
{
|
{
|
||||||
RARCH_ERR("[GL]: Renderchain could not be initialized.\n");
|
RARCH_ERR("[GL]: Renderchain could not be initialized.\n");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,7 @@ typedef struct gfx_ctx_wayland_data
|
||||||
#endif
|
#endif
|
||||||
} gfx_ctx_wayland_data_t;
|
} gfx_ctx_wayland_data_t;
|
||||||
|
|
||||||
|
|
||||||
static enum gfx_ctx_api wl_api = GFX_CTX_NONE;
|
static enum gfx_ctx_api wl_api = GFX_CTX_NONE;
|
||||||
|
|
||||||
#ifndef EGL_OPENGL_ES3_BIT_KHR
|
#ifndef EGL_OPENGL_ES3_BIT_KHR
|
||||||
|
@ -354,9 +355,10 @@ static void touch_handle_down(void *data,
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||||
|
|
||||||
if (num_active_touches < MAX_TOUCHES)
|
if (num_active_touches < MAX_TOUCHES)
|
||||||
{
|
{
|
||||||
for (i=0; i<MAX_TOUCHES; i++)
|
for (i = 0; i < MAX_TOUCHES; i++)
|
||||||
{
|
{
|
||||||
/* Use next empty slot */
|
/* Use next empty slot */
|
||||||
if (!active_touch_positions[i].active)
|
if (!active_touch_positions[i].active)
|
||||||
|
@ -371,13 +373,13 @@ static void touch_handle_down(void *data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void reorder_touches()
|
static void reorder_touches(void)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
if (num_active_touches == 0)
|
if (num_active_touches == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (i=0; i<MAX_TOUCHES; i++)
|
for (i = 0; i < MAX_TOUCHES; i++)
|
||||||
{
|
{
|
||||||
if (!active_touch_positions[i].active)
|
if (!active_touch_positions[i].active)
|
||||||
{
|
{
|
||||||
|
@ -410,7 +412,7 @@ static void touch_handle_up(void *data,
|
||||||
int i;
|
int i;
|
||||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||||
|
|
||||||
for (i=0; i<MAX_TOUCHES; i++)
|
for (i = 0; i < MAX_TOUCHES; i++)
|
||||||
{
|
{
|
||||||
if (active_touch_positions[i].active && active_touch_positions[i].id == id)
|
if (active_touch_positions[i].active && active_touch_positions[i].id == id)
|
||||||
{
|
{
|
||||||
|
@ -421,7 +423,7 @@ static void touch_handle_up(void *data,
|
||||||
num_active_touches--;
|
num_active_touches--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reorder_touches(wl);
|
reorder_touches();
|
||||||
}
|
}
|
||||||
static void touch_handle_motion(void *data,
|
static void touch_handle_motion(void *data,
|
||||||
struct wl_touch *wl_touch,
|
struct wl_touch *wl_touch,
|
||||||
|
@ -432,7 +434,8 @@ static void touch_handle_motion(void *data,
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||||
for (i=0; i<MAX_TOUCHES; i++)
|
|
||||||
|
for (i = 0; i < MAX_TOUCHES; i++)
|
||||||
{
|
{
|
||||||
if (active_touch_positions[i].active && active_touch_positions[i].id == id)
|
if (active_touch_positions[i].active && active_touch_positions[i].id == id)
|
||||||
{
|
{
|
||||||
|
@ -453,7 +456,8 @@ static void touch_handle_cancel(void *data,
|
||||||
* since they were not ment for us anyway */
|
* since they were not ment for us anyway */
|
||||||
int i;
|
int i;
|
||||||
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
gfx_ctx_wayland_data_t *wl = (gfx_ctx_wayland_data_t*)data;
|
||||||
for (i=0; i<MAX_TOUCHES; i++)
|
|
||||||
|
for (i = 0; i < MAX_TOUCHES; i++)
|
||||||
{
|
{
|
||||||
active_touch_positions[i].active = false;
|
active_touch_positions[i].active = false;
|
||||||
active_touch_positions[i].id = -1;
|
active_touch_positions[i].id = -1;
|
||||||
|
@ -1105,7 +1109,7 @@ static void *gfx_ctx_wl_init(video_frame_info_t *video_info, void *video_driver)
|
||||||
wl->cursor.default_cursor = wl_cursor_theme_get_cursor(wl->cursor.theme, "left_ptr");
|
wl->cursor.default_cursor = wl_cursor_theme_get_cursor(wl->cursor.theme, "left_ptr");
|
||||||
|
|
||||||
num_active_touches = 0;
|
num_active_touches = 0;
|
||||||
for (i=0;i<MAX_TOUCHES;i++)
|
for (i = 0;i < MAX_TOUCHES;i++)
|
||||||
{
|
{
|
||||||
active_touch_positions[i].active = false;
|
active_touch_positions[i].active = false;
|
||||||
active_touch_positions[i].id = -1;
|
active_touch_positions[i].id = -1;
|
||||||
|
|
|
@ -503,8 +503,8 @@ bool video_shader_resolve_parameters(config_file_t *conf,
|
||||||
char *line = NULL;
|
char *line = NULL;
|
||||||
const char *path = shader->pass[i].source.path;
|
const char *path = shader->pass[i].source.path;
|
||||||
|
|
||||||
if (string_is_empty(path))
|
if (string_is_empty(path))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS)
|
#if defined(HAVE_SLANG) && defined(HAVE_SPIRV_CROSS)
|
||||||
/* First try to use the more robust slang
|
/* First try to use the more robust slang
|
||||||
|
@ -529,6 +529,9 @@ bool video_shader_resolve_parameters(config_file_t *conf,
|
||||||
line = (char*)malloc(4096 * sizeof(char));
|
line = (char*)malloc(4096 * sizeof(char));
|
||||||
line[0] = '\0';
|
line[0] = '\0';
|
||||||
|
|
||||||
|
/* even though the pass is set in the loop too, not all passes have parameters */
|
||||||
|
param->pass = i;
|
||||||
|
|
||||||
while (shader->num_parameters < ARRAY_SIZE(shader->parameters)
|
while (shader->num_parameters < ARRAY_SIZE(shader->parameters)
|
||||||
&& intfstream_gets(file, line, line_size))
|
&& intfstream_gets(file, line, line_size))
|
||||||
{
|
{
|
||||||
|
|
|
@ -99,29 +99,28 @@ static int16_t input_wl_lightgun_state(input_ctx_wayland_data_t *wl, unsigned id
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* forward declaration */
|
||||||
|
bool wayland_context_gettouchpos(void *data, unsigned id,
|
||||||
|
unsigned* touch_x, unsigned* touch_y);
|
||||||
|
|
||||||
static void input_wl_touch_pool(void *data)
|
static void input_wl_touch_pool(void *data)
|
||||||
{
|
{
|
||||||
int id;
|
int id;
|
||||||
|
unsigned touch_x = 0;
|
||||||
|
unsigned touch_y = 0;
|
||||||
input_ctx_wayland_data_t *wl = (input_ctx_wayland_data_t*)data;
|
input_ctx_wayland_data_t *wl = (input_ctx_wayland_data_t*)data;
|
||||||
|
|
||||||
if (!wl)
|
if (!wl)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned touch_x = 0;
|
for (id = 0; id < MAX_TOUCHES; id++)
|
||||||
unsigned touch_y = 0;
|
|
||||||
|
|
||||||
for (id=0; id<MAX_TOUCHES; id++)
|
|
||||||
{
|
{
|
||||||
if (wayland_context_gettouchpos(wl, id, &touch_x, &touch_y))
|
if (wayland_context_gettouchpos(wl, id, &touch_x, &touch_y))
|
||||||
{
|
|
||||||
wl->touches[id].active = true;
|
wl->touches[id].active = true;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
|
||||||
wl->touches[id].active = false;
|
wl->touches[id].active = false;
|
||||||
}
|
wl->touches[id].x = touch_x;
|
||||||
wl->touches[id].x = touch_x;
|
wl->touches[id].y = touch_y;
|
||||||
wl->touches[id].y = touch_y;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
#include <file/nbio.h>
|
#include <file/nbio.h>
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(_XBOX)
|
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
|
@ -2505,15 +2505,18 @@ static uint8_t *rjpeg_load_jpeg_image(rjpeg__jpeg *z,
|
||||||
if (n >= 3)
|
if (n >= 3)
|
||||||
{
|
{
|
||||||
uint8_t *y = coutput[0];
|
uint8_t *y = coutput[0];
|
||||||
if (z->s->img_n == 3)
|
if (y)
|
||||||
z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
|
{
|
||||||
else
|
if (z->s->img_n == 3)
|
||||||
for (i=0; i < z->s->img_x; ++i)
|
z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n);
|
||||||
{
|
else
|
||||||
out[0] = out[1] = out[2] = y[i];
|
for (i=0; i < z->s->img_x; ++i)
|
||||||
out[3] = 255; /* not used if n==3 */
|
{
|
||||||
out += n;
|
out[0] = out[1] = out[2] = y[i];
|
||||||
}
|
out[3] = 255; /* not used if n==3 */
|
||||||
|
out += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -544,6 +544,7 @@ static int png_reverse_filter_init(const struct png_ihdr *ihdr,
|
||||||
if (pngp->pass_size > pngp->total_out)
|
if (pngp->pass_size > pngp->total_out)
|
||||||
{
|
{
|
||||||
free(pngp->data);
|
free(pngp->data);
|
||||||
|
pngp->data = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -721,6 +722,7 @@ static int png_reverse_filter_adam7_iterate(uint32_t **data_,
|
||||||
|
|
||||||
free(pngp->data);
|
free(pngp->data);
|
||||||
|
|
||||||
|
pngp->data = NULL;
|
||||||
pngp->pass_width = 0;
|
pngp->pass_width = 0;
|
||||||
pngp->pass_height = 0;
|
pngp->pass_height = 0;
|
||||||
pngp->pass_size = 0;
|
pngp->pass_size = 0;
|
||||||
|
@ -746,7 +748,10 @@ static int png_reverse_filter_adam7(uint32_t **data_,
|
||||||
return 0;
|
return 0;
|
||||||
case IMAGE_PROCESS_ERROR:
|
case IMAGE_PROCESS_ERROR:
|
||||||
if (pngp->data)
|
if (pngp->data)
|
||||||
|
{
|
||||||
free(pngp->data);
|
free(pngp->data);
|
||||||
|
pngp->data = NULL;
|
||||||
|
}
|
||||||
pngp->inflate_buf -= pngp->adam7_restore_buf_size;
|
pngp->inflate_buf -= pngp->adam7_restore_buf_size;
|
||||||
pngp->adam7_restore_buf_size = 0;
|
pngp->adam7_restore_buf_size = 0;
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -543,17 +543,20 @@ static void materialui_render_messagebox(materialui_handle_t *mui,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
menu_display_set_alpha(body_bg_color, 1.0);
|
if (body_bg_color)
|
||||||
|
{
|
||||||
|
menu_display_set_alpha(body_bg_color, 1.0);
|
||||||
|
|
||||||
menu_display_draw_quad(
|
menu_display_draw_quad(
|
||||||
video_info,
|
video_info,
|
||||||
x - longest_width / 2.0 - mui->margin * 2.0,
|
x - longest_width / 2.0 - mui->margin * 2.0,
|
||||||
y - line_height / 2.0 - mui->margin * 2.0,
|
y - line_height / 2.0 - mui->margin * 2.0,
|
||||||
longest_width + mui->margin * 4.0,
|
longest_width + mui->margin * 4.0,
|
||||||
line_height * list->size + mui->margin * 4.0,
|
line_height * list->size + mui->margin * 4.0,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
&body_bg_color[0]);
|
&body_bg_color[0]);
|
||||||
|
}
|
||||||
|
|
||||||
/* print each line */
|
/* print each line */
|
||||||
for (i = 0; i < list->size; i++)
|
for (i = 0; i < list->size; i++)
|
||||||
|
|
|
@ -30,6 +30,7 @@ import android.util.Log;
|
||||||
public final class MainMenuActivity extends PreferenceActivity
|
public final class MainMenuActivity extends PreferenceActivity
|
||||||
{
|
{
|
||||||
final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
|
final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
|
||||||
|
public static String PACKAGE_NAME;
|
||||||
boolean checkPermissions = false;
|
boolean checkPermissions = false;
|
||||||
|
|
||||||
public void showMessageOKCancel(String message, DialogInterface.OnClickListener onClickListener)
|
public void showMessageOKCancel(String message, DialogInterface.OnClickListener onClickListener)
|
||||||
|
@ -181,7 +182,7 @@ public final class MainMenuActivity extends PreferenceActivity
|
||||||
retro.putExtra("SDCARD", Environment.getExternalStorageDirectory().getAbsolutePath());
|
retro.putExtra("SDCARD", Environment.getExternalStorageDirectory().getAbsolutePath());
|
||||||
retro.putExtra("DOWNLOADS", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath());
|
retro.putExtra("DOWNLOADS", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath());
|
||||||
retro.putExtra("SCREENSHOTS", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath());
|
retro.putExtra("SCREENSHOTS", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath());
|
||||||
String external = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/com.retroarch/files";
|
String external = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/" + PACKAGE_NAME + "/files";
|
||||||
retro.putExtra("EXTERNAL", external);
|
retro.putExtra("EXTERNAL", external);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,6 +191,8 @@ public final class MainMenuActivity extends PreferenceActivity
|
||||||
{
|
{
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
|
PACKAGE_NAME = getPackageName();
|
||||||
|
|
||||||
// Bind audio stream to hardware controls.
|
// Bind audio stream to hardware controls.
|
||||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||||
|
|
||||||
|
|
|
@ -14,4 +14,4 @@
|
||||||
# 'key.store' for the location of your keystore and
|
# 'key.store' for the location of your keystore and
|
||||||
# 'key.alias' for the name of the key to use.
|
# 'key.alias' for the name of the key to use.
|
||||||
# The password will be asked during the build when you use the 'release' target.
|
# The password will be asked during the build when you use the 'release' target.
|
||||||
|
source.dir=../phoenix/src
|
||||||
|
|
|
@ -1,200 +0,0 @@
|
||||||
package com.retroarch.browser.mainmenu;
|
|
||||||
|
|
||||||
import com.retroarch.browser.preferences.util.UserPreferences;
|
|
||||||
import com.retroarch.browser.retroactivity.RetroActivityFuture;
|
|
||||||
import com.retroarch.browser.retroactivity.RetroActivityPast;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.pm.ApplicationInfo;
|
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.os.Environment;
|
|
||||||
import android.preference.PreferenceActivity;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.provider.Settings;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.Manifest;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link PreferenceActivity} subclass that provides all of the
|
|
||||||
* functionality of the main menu screen.
|
|
||||||
*/
|
|
||||||
public final class MainMenuActivity extends PreferenceActivity
|
|
||||||
{
|
|
||||||
final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
|
|
||||||
boolean checkPermissions = false;
|
|
||||||
|
|
||||||
public void showMessageOKCancel(String message, DialogInterface.OnClickListener onClickListener)
|
|
||||||
{
|
|
||||||
new AlertDialog.Builder(this).setMessage(message)
|
|
||||||
.setPositiveButton("OK", onClickListener).setCancelable(false)
|
|
||||||
.setNegativeButton("Cancel", null).create().show();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean addPermission(List<String> permissionsList, String permission)
|
|
||||||
{
|
|
||||||
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED)
|
|
||||||
{
|
|
||||||
permissionsList.add(permission);
|
|
||||||
|
|
||||||
// Check for Rationale Option
|
|
||||||
if (!shouldShowRequestPermissionRationale(permission))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void checkRuntimePermissions()
|
|
||||||
{
|
|
||||||
if (android.os.Build.VERSION.SDK_INT >= 23)
|
|
||||||
{
|
|
||||||
// Android 6.0+ needs runtime permission checks
|
|
||||||
List<String> permissionsNeeded = new ArrayList<String>();
|
|
||||||
final List<String> permissionsList = new ArrayList<String>();
|
|
||||||
|
|
||||||
if (!addPermission(permissionsList, Manifest.permission.READ_EXTERNAL_STORAGE))
|
|
||||||
permissionsNeeded.add("Read External Storage");
|
|
||||||
if (!addPermission(permissionsList, Manifest.permission.WRITE_EXTERNAL_STORAGE))
|
|
||||||
permissionsNeeded.add("Write External Storage");
|
|
||||||
|
|
||||||
if (permissionsList.size() > 0)
|
|
||||||
{
|
|
||||||
checkPermissions = true;
|
|
||||||
|
|
||||||
if (permissionsNeeded.size() > 0)
|
|
||||||
{
|
|
||||||
// Need Rationale
|
|
||||||
Log.i("MainMenuActivity", "Need to request external storage permissions.");
|
|
||||||
|
|
||||||
String message = "You need to grant access to " + permissionsNeeded.get(0);
|
|
||||||
|
|
||||||
for (int i = 1; i < permissionsNeeded.size(); i++)
|
|
||||||
message = message + ", " + permissionsNeeded.get(i);
|
|
||||||
|
|
||||||
showMessageOKCancel(message,
|
|
||||||
new DialogInterface.OnClickListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onClick(DialogInterface dialog, int which)
|
|
||||||
{
|
|
||||||
if (which == AlertDialog.BUTTON_POSITIVE)
|
|
||||||
{
|
|
||||||
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
|
|
||||||
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
|
|
||||||
|
|
||||||
Log.i("MainMenuActivity", "User accepted request for external storage permissions.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
|
|
||||||
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
|
|
||||||
|
|
||||||
Log.i("MainMenuActivity", "Requested external storage permissions.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!checkPermissions)
|
|
||||||
{
|
|
||||||
finalStartup();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finalStartup()
|
|
||||||
{
|
|
||||||
final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
|
||||||
Intent retro;
|
|
||||||
|
|
||||||
if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB))
|
|
||||||
{
|
|
||||||
retro = new Intent(this, RetroActivityFuture.class);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
retro = new Intent(this, RetroActivityPast.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
retro.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
||||||
|
|
||||||
startRetroActivity(
|
|
||||||
retro,
|
|
||||||
null,
|
|
||||||
prefs.getString("libretro_path", getApplicationInfo().dataDir + "/cores/"),
|
|
||||||
UserPreferences.getDefaultConfigPath(this),
|
|
||||||
Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD),
|
|
||||||
getApplicationInfo().dataDir,
|
|
||||||
getApplicationInfo().sourceDir);
|
|
||||||
startActivity(retro);
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
|
|
||||||
{
|
|
||||||
switch (requestCode)
|
|
||||||
{
|
|
||||||
case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS:
|
|
||||||
for (int i = 0; i < permissions.length; i++)
|
|
||||||
{
|
|
||||||
if(grantResults[i] == PackageManager.PERMISSION_GRANTED)
|
|
||||||
{
|
|
||||||
Log.i("MainMenuActivity", "Permission: " + permissions[i] + " was granted.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.i("MainMenuActivity", "Permission: " + permissions[i] + " was not granted.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
finalStartup();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void startRetroActivity(Intent retro, String contentPath, String corePath,
|
|
||||||
String configFilePath, String imePath, String dataDirPath, String dataSourcePath)
|
|
||||||
{
|
|
||||||
if (contentPath != null) {
|
|
||||||
retro.putExtra("ROM", contentPath);
|
|
||||||
}
|
|
||||||
retro.putExtra("LIBRETRO", corePath);
|
|
||||||
retro.putExtra("CONFIGFILE", configFilePath);
|
|
||||||
retro.putExtra("IME", imePath);
|
|
||||||
retro.putExtra("DATADIR", dataDirPath);
|
|
||||||
retro.putExtra("APK", dataSourcePath);
|
|
||||||
retro.putExtra("SDCARD", Environment.getExternalStorageDirectory().getAbsolutePath());
|
|
||||||
retro.putExtra("DOWNLOADS", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath());
|
|
||||||
retro.putExtra("SCREENSHOTS", Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath());
|
|
||||||
String external = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Android/data/com.retroarch.aarch64/files";
|
|
||||||
retro.putExtra("EXTERNAL", external);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
|
|
||||||
// Bind audio stream to hardware controls.
|
|
||||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
|
||||||
|
|
||||||
UserPreferences.updateConfigFile(this);
|
|
||||||
|
|
||||||
checkRuntimePermissions();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,281 +0,0 @@
|
||||||
package com.retroarch.browser.preferences.util;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.PrintWriter;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a configuration file that works off of a key-value pair
|
|
||||||
* in the form [key name] = "[value]".
|
|
||||||
*/
|
|
||||||
public final class ConfigFile
|
|
||||||
{
|
|
||||||
// Map containing all of the key-value pairs.
|
|
||||||
private final HashMap<String, String> map = new HashMap<String, String>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*/
|
|
||||||
public ConfigFile()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor
|
|
||||||
*
|
|
||||||
* @param filePath The path to the configuration file to open.
|
|
||||||
*/
|
|
||||||
public ConfigFile(String filePath)
|
|
||||||
{
|
|
||||||
if (filePath == null)
|
|
||||||
throw new IllegalArgumentException("filePath cannot be null.");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
open(filePath);
|
|
||||||
}
|
|
||||||
catch (IOException ioe)
|
|
||||||
{
|
|
||||||
Log.e("ConfigFile", "Stream reading the configuration file was suddenly closed for an unknown reason.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parses a configuration file from the given stream
|
|
||||||
* and appends the parsed values to the key-value map.
|
|
||||||
*
|
|
||||||
* @param stream The {@link InputStream} containing the configuration file to parse.
|
|
||||||
*/
|
|
||||||
public void append(InputStream stream) throws IOException
|
|
||||||
{
|
|
||||||
BufferedReader br = new BufferedReader(new InputStreamReader(stream));
|
|
||||||
|
|
||||||
String line;
|
|
||||||
while ((line = br.readLine()) != null)
|
|
||||||
parseLine(line);
|
|
||||||
|
|
||||||
br.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens a configuration file given by configPath
|
|
||||||
* and parses all of its key-value pairs, adding
|
|
||||||
* them to the key-value map.
|
|
||||||
*
|
|
||||||
* @param configPath Path to the configuration file to parse.
|
|
||||||
*/
|
|
||||||
public void open(String configPath) throws IOException
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
append(new FileInputStream(configPath));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void parseLine(String line)
|
|
||||||
{
|
|
||||||
String[] tokens = line.split("=", 2);
|
|
||||||
if (tokens.length < 2)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (int i = 0; i < tokens.length; i++)
|
|
||||||
tokens[i] = tokens[i].trim();
|
|
||||||
|
|
||||||
String key = tokens[0];
|
|
||||||
String value = tokens[1];
|
|
||||||
|
|
||||||
if (value.startsWith("\""))
|
|
||||||
value = value.substring(1, value.lastIndexOf('\"'));
|
|
||||||
else
|
|
||||||
value = value.split(" ")[0];
|
|
||||||
|
|
||||||
if (value.length() > 0)
|
|
||||||
map.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the key-value map of all currently set keys and values.
|
|
||||||
*/
|
|
||||||
public void clear()
|
|
||||||
{
|
|
||||||
map.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes the currently set key-value pairs to
|
|
||||||
*
|
|
||||||
* @param path The path to save the
|
|
||||||
*
|
|
||||||
* @throws IOException
|
|
||||||
*/
|
|
||||||
public void write(String path) throws IOException
|
|
||||||
{
|
|
||||||
PrintWriter writer = new PrintWriter(path);
|
|
||||||
|
|
||||||
for (Map.Entry<String, String> entry : map.entrySet())
|
|
||||||
{
|
|
||||||
writer.println(entry.getKey() + " = \"" + entry.getValue() + "\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if a key exists in the {@link HashMap}
|
|
||||||
* backing this ConfigFile instance.
|
|
||||||
*
|
|
||||||
* @param key The key to check for.
|
|
||||||
*
|
|
||||||
* @return true if the key exists in the HashMap backing
|
|
||||||
* this ConfigFile; false if it doesn't.
|
|
||||||
*/
|
|
||||||
public boolean keyExists(String key)
|
|
||||||
{
|
|
||||||
return map.containsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a key to the given String value.
|
|
||||||
*
|
|
||||||
* @param key The key to set the String value to.
|
|
||||||
* @param value The String value to set to the key.
|
|
||||||
*/
|
|
||||||
public void setString(String key, String value)
|
|
||||||
{
|
|
||||||
map.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a key to the given boolean value.
|
|
||||||
*
|
|
||||||
* @param key The key to set the boolean value to.
|
|
||||||
* @param value The boolean value to set to the key.
|
|
||||||
*/
|
|
||||||
public void setBoolean(String key, boolean value)
|
|
||||||
{
|
|
||||||
map.put(key, Boolean.toString(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a key to the given Integer value.
|
|
||||||
*
|
|
||||||
* @param key The key to set the Integer value to.
|
|
||||||
* @param value The Integer value to set to the key.
|
|
||||||
*/
|
|
||||||
public void setInt(String key, int value)
|
|
||||||
{
|
|
||||||
map.put(key, Integer.toString(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a key to the given double value.
|
|
||||||
*
|
|
||||||
* @param key The key to set the double value to.
|
|
||||||
* @param value The double value to set to the key.
|
|
||||||
*/
|
|
||||||
public void setDouble(String key, double value)
|
|
||||||
{
|
|
||||||
map.put(key, Double.toString(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a key to the given float value.
|
|
||||||
*
|
|
||||||
* @param key The key to set the float value to.
|
|
||||||
* @param value The float value to set to the key.
|
|
||||||
*/
|
|
||||||
public void setFloat(String key, float value)
|
|
||||||
{
|
|
||||||
map.put(key, Float.toString(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the String value associated with the given key.
|
|
||||||
*
|
|
||||||
* @param key The key to get the String value from.
|
|
||||||
*
|
|
||||||
* @return the String object associated with the given key.
|
|
||||||
*/
|
|
||||||
public String getString(String key)
|
|
||||||
{
|
|
||||||
String ret = map.get(key);
|
|
||||||
|
|
||||||
if (ret != null)
|
|
||||||
return ret;
|
|
||||||
else
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the Integer value associated with the given key.
|
|
||||||
*
|
|
||||||
* @param key The key to get the Integer value from.
|
|
||||||
*
|
|
||||||
* @return the Integer value associated with the given key.
|
|
||||||
*/
|
|
||||||
public int getInt(String key)
|
|
||||||
{
|
|
||||||
String str = getString(key);
|
|
||||||
|
|
||||||
if (str != null)
|
|
||||||
return Integer.parseInt(str);
|
|
||||||
else
|
|
||||||
throw new IllegalArgumentException("Config key '" + key + "' is invalid.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the double value associated with the given key.
|
|
||||||
*
|
|
||||||
* @param key The key to get the double value from.
|
|
||||||
*
|
|
||||||
* @return the double value associated with the given key.
|
|
||||||
*/
|
|
||||||
public double getDouble(String key)
|
|
||||||
{
|
|
||||||
String str = getString(key);
|
|
||||||
|
|
||||||
if (str != null)
|
|
||||||
return Double.parseDouble(str);
|
|
||||||
else
|
|
||||||
throw new IllegalArgumentException("Config key '" + key + "' is invalid.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the float value associated with the given key.
|
|
||||||
*
|
|
||||||
* @param key The key to get the float value from.
|
|
||||||
*
|
|
||||||
* @return the float value associated with the given key.
|
|
||||||
*/
|
|
||||||
public float getFloat(String key)
|
|
||||||
{
|
|
||||||
String str = getString(key);
|
|
||||||
|
|
||||||
if (str != null)
|
|
||||||
return Float.parseFloat(str);
|
|
||||||
else
|
|
||||||
throw new IllegalArgumentException("Config key '" + key + "' is invalid.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the boolean value associated with the given key.
|
|
||||||
*
|
|
||||||
* @param key The key to get the boolean value from.
|
|
||||||
*
|
|
||||||
* @return the boolean value associated with the given key.
|
|
||||||
*/
|
|
||||||
public boolean getBoolean(String key)
|
|
||||||
{
|
|
||||||
String str = getString(key);
|
|
||||||
|
|
||||||
if (str != null)
|
|
||||||
return Boolean.parseBoolean(str);
|
|
||||||
else
|
|
||||||
throw new IllegalArgumentException("Config key '" + key + "' is invalid.");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,300 +0,0 @@
|
||||||
package com.retroarch.browser.preferences.util;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.media.AudioManager;
|
|
||||||
import android.media.AudioTrack;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utility class for retrieving, saving, or loading preferences.
|
|
||||||
*/
|
|
||||||
public final class UserPreferences
|
|
||||||
{
|
|
||||||
// Logging tag.
|
|
||||||
private static final String TAG = "UserPreferences";
|
|
||||||
|
|
||||||
// Disallow explicit instantiation.
|
|
||||||
private UserPreferences()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves the path to the default location of the libretro config.
|
|
||||||
*
|
|
||||||
* @param ctx the current {@link Context}
|
|
||||||
*
|
|
||||||
* @return the path to the default location of the libretro config.
|
|
||||||
*/
|
|
||||||
public static String getDefaultConfigPath(Context ctx)
|
|
||||||
{
|
|
||||||
// Internal/External storage dirs.
|
|
||||||
final String internal = ctx.getFilesDir().getAbsolutePath();
|
|
||||||
String external = null;
|
|
||||||
|
|
||||||
// Get the App's external storage folder
|
|
||||||
final String state = android.os.Environment.getExternalStorageState();
|
|
||||||
if (android.os.Environment.MEDIA_MOUNTED.equals(state)) {
|
|
||||||
File extsd = ctx.getExternalFilesDir(null);
|
|
||||||
external = extsd.getAbsolutePath();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Native library directory and data directory for this front-end.
|
|
||||||
final String dataDir = ctx.getApplicationInfo().dataDir;
|
|
||||||
final String coreDir = dataDir + "/cores/";
|
|
||||||
|
|
||||||
// Get libretro name and path
|
|
||||||
final SharedPreferences prefs = getPreferences(ctx);
|
|
||||||
final String libretro_path = prefs.getString("libretro_path", coreDir);
|
|
||||||
|
|
||||||
// Check if global config is being used. Return true upon failure.
|
|
||||||
final boolean globalConfigEnabled = prefs.getBoolean("global_config_enable", true);
|
|
||||||
|
|
||||||
String append_path;
|
|
||||||
// If we aren't using the global config.
|
|
||||||
if (!globalConfigEnabled && !libretro_path.equals(coreDir))
|
|
||||||
{
|
|
||||||
String sanitized_name = sanitizeLibretroPath(libretro_path);
|
|
||||||
append_path = File.separator + sanitized_name + ".cfg";
|
|
||||||
}
|
|
||||||
else // Using global config.
|
|
||||||
{
|
|
||||||
append_path = File.separator + "retroarch.cfg";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (external != null)
|
|
||||||
{
|
|
||||||
String confPath = external + append_path;
|
|
||||||
if (new File(confPath).exists())
|
|
||||||
return confPath;
|
|
||||||
}
|
|
||||||
else if (internal != null)
|
|
||||||
{
|
|
||||||
String confPath = internal + append_path;
|
|
||||||
if (new File(confPath).exists())
|
|
||||||
return confPath;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
String confPath = "/mnt/extsd" + append_path;
|
|
||||||
if (new File(confPath).exists())
|
|
||||||
return confPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Config file does not exist. Create empty one.
|
|
||||||
|
|
||||||
// emergency fallback
|
|
||||||
String new_path = "/mnt/sd" + append_path;
|
|
||||||
|
|
||||||
if (external != null)
|
|
||||||
new_path = external + append_path;
|
|
||||||
else if (internal != null)
|
|
||||||
new_path = internal + append_path;
|
|
||||||
else if (dataDir != null)
|
|
||||||
new_path = dataDir + append_path;
|
|
||||||
|
|
||||||
try {
|
|
||||||
new File(new_path).createNewFile();
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
Log.e(TAG, "Failed to create config file to: " + new_path);
|
|
||||||
}
|
|
||||||
return new_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the libretro configuration file
|
|
||||||
* with new values if settings have changed.
|
|
||||||
*
|
|
||||||
* @param ctx the current {@link Context}.
|
|
||||||
*/
|
|
||||||
public static void updateConfigFile(Context ctx)
|
|
||||||
{
|
|
||||||
String path = getDefaultConfigPath(ctx);
|
|
||||||
ConfigFile config = new ConfigFile(path);
|
|
||||||
|
|
||||||
Log.i(TAG, "Writing config to: " + path);
|
|
||||||
|
|
||||||
final String dataDir = ctx.getApplicationInfo().dataDir;
|
|
||||||
final String coreDir = dataDir + "/cores/";
|
|
||||||
|
|
||||||
final SharedPreferences prefs = getPreferences(ctx);
|
|
||||||
|
|
||||||
config.setString("libretro_directory", coreDir);
|
|
||||||
config.setInt("audio_out_rate", getOptimalSamplingRate(ctx));
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int version = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), 0).versionCode;
|
|
||||||
final String dst_path = dataDir;
|
|
||||||
final String dst_path_subdir = "assets";
|
|
||||||
|
|
||||||
Log.i(TAG, "dst dir is: " + dst_path);
|
|
||||||
Log.i(TAG, "dst subdir is: " + dst_path_subdir);
|
|
||||||
|
|
||||||
config.setBoolean("log_verbosity", true);
|
|
||||||
config.setString("bundle_assets_src_path", ctx.getApplicationInfo().sourceDir);
|
|
||||||
config.setString("bundle_assets_dst_path", dst_path);
|
|
||||||
config.setString("bundle_assets_dst_path_subdir", dst_path_subdir);
|
|
||||||
config.setInt("bundle_assets_extract_version_current", version);
|
|
||||||
}
|
|
||||||
catch (NameNotFoundException ignored)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refactor this entire mess and make this usable for per-core config
|
|
||||||
if (Build.VERSION.SDK_INT >= 17 && prefs.getBoolean("audio_latency_auto", true))
|
|
||||||
{
|
|
||||||
config.setInt("audio_block_frames", getLowLatencyBufferSize(ctx));
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
config.write(path);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
Log.e(TAG, "Failed to save config file to: " + path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void readbackString(ConfigFile cfg, SharedPreferences.Editor edit, String key)
|
|
||||||
{
|
|
||||||
if (cfg.keyExists(key))
|
|
||||||
edit.putString(key, cfg.getString(key));
|
|
||||||
else
|
|
||||||
edit.remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void readbackBool(ConfigFile cfg, SharedPreferences.Editor edit, String key)
|
|
||||||
{
|
|
||||||
if (cfg.keyExists(key))
|
|
||||||
edit.putBoolean(key, cfg.getBoolean(key));
|
|
||||||
else
|
|
||||||
edit.remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void readbackDouble(ConfigFile cfg, SharedPreferences.Editor edit, String key)
|
|
||||||
{
|
|
||||||
if (cfg.keyExists(key))
|
|
||||||
edit.putFloat(key, (float)cfg.getDouble(key));
|
|
||||||
else
|
|
||||||
edit.remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
private static void readbackFloat(ConfigFile cfg, SharedPreferences.Editor edit, String key)
|
|
||||||
{
|
|
||||||
if (cfg.keyExists(key))
|
|
||||||
edit.putFloat(key, cfg.getFloat(key));
|
|
||||||
else
|
|
||||||
edit.remove(key);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
private static void readbackInt(ConfigFile cfg, SharedPreferences.Editor edit, String key)
|
|
||||||
{
|
|
||||||
if (cfg.keyExists(key))
|
|
||||||
edit.putInt(key, cfg.getInt(key));
|
|
||||||
else
|
|
||||||
edit.remove(key);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sanitizes a libretro core path.
|
|
||||||
*
|
|
||||||
* @param path The path to the libretro core.
|
|
||||||
*
|
|
||||||
* @return the sanitized libretro path.
|
|
||||||
*/
|
|
||||||
private static String sanitizeLibretroPath(String path)
|
|
||||||
{
|
|
||||||
String sanitized_name = path.substring(
|
|
||||||
path.lastIndexOf('/') + 1,
|
|
||||||
path.lastIndexOf('.'));
|
|
||||||
sanitized_name = sanitized_name.replace("neon", "");
|
|
||||||
sanitized_name = sanitized_name.replace("libretro_", "");
|
|
||||||
|
|
||||||
return sanitized_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a {@link SharedPreferences} instance containing current settings.
|
|
||||||
*
|
|
||||||
* @param ctx the current {@link Context}.
|
|
||||||
*
|
|
||||||
* @return A SharedPreference instance containing current settings.
|
|
||||||
*/
|
|
||||||
public static SharedPreferences getPreferences(Context ctx)
|
|
||||||
{
|
|
||||||
return PreferenceManager.getDefaultSharedPreferences(ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the optimal sampling rate for low-latency audio playback.
|
|
||||||
*
|
|
||||||
* @param ctx the current {@link Context}.
|
|
||||||
*
|
|
||||||
* @return the optimal sampling rate for low-latency audio playback in Hz.
|
|
||||||
*/
|
|
||||||
@TargetApi(17)
|
|
||||||
private static int getLowLatencyOptimalSamplingRate(Context ctx)
|
|
||||||
{
|
|
||||||
AudioManager manager = (AudioManager) ctx.getSystemService(Context.AUDIO_SERVICE);
|
|
||||||
|
|
||||||
return Integer.parseInt(manager
|
|
||||||
.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the optimal buffer size for low-latency audio playback.
|
|
||||||
*
|
|
||||||
* @param ctx the current {@link Context}.
|
|
||||||
*
|
|
||||||
* @return the optimal output buffer size in decimal PCM frames.
|
|
||||||
*/
|
|
||||||
@TargetApi(17)
|
|
||||||
private static int getLowLatencyBufferSize(Context ctx)
|
|
||||||
{
|
|
||||||
AudioManager manager = (AudioManager) ctx.getSystemService(Context.AUDIO_SERVICE);
|
|
||||||
int buffersize = Integer.parseInt(manager
|
|
||||||
.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER));
|
|
||||||
Log.i(TAG, "Queried ideal buffer size (frames): " + buffersize);
|
|
||||||
return buffersize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the optimal audio sampling rate.
|
|
||||||
* <p>
|
|
||||||
* On Android 4.2+ devices this will retrieve the optimal low-latency sampling rate,
|
|
||||||
* since Android 4.2 adds support for low latency audio in general.
|
|
||||||
* <p>
|
|
||||||
* On other devices, it simply returns the regular optimal sampling rate
|
|
||||||
* as returned by the hardware.
|
|
||||||
*
|
|
||||||
* @param ctx The current {@link Context}.
|
|
||||||
*
|
|
||||||
* @return the optimal audio sampling rate in Hz.
|
|
||||||
*/
|
|
||||||
private static int getOptimalSamplingRate(Context ctx)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
if (Build.VERSION.SDK_INT >= 17)
|
|
||||||
ret = getLowLatencyOptimalSamplingRate(ctx);
|
|
||||||
else
|
|
||||||
ret = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
|
|
||||||
|
|
||||||
Log.i(TAG, "Using sampling rate: " + ret + " Hz");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,225 +0,0 @@
|
||||||
package com.retroarch.browser.retroactivity;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import com.retroarch.browser.preferences.util.UserPreferences;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.graphics.SurfaceTexture;
|
|
||||||
import android.graphics.SurfaceTexture.OnFrameAvailableListener;
|
|
||||||
import android.hardware.Camera;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
//For Android 3.0 and up
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class which provides {@link Camera} functionality
|
|
||||||
* to {@link RetroActivityFuture}.
|
|
||||||
*/
|
|
||||||
@SuppressLint("NewApi")
|
|
||||||
public class RetroActivityCamera extends RetroActivityCommon
|
|
||||||
{
|
|
||||||
private Camera mCamera = null;
|
|
||||||
private long lastTimestamp = 0;
|
|
||||||
private SurfaceTexture texture;
|
|
||||||
private boolean updateSurface = true;
|
|
||||||
private boolean camera_service_running = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executed when the {@link Camera}
|
|
||||||
* is staring to capture.
|
|
||||||
*/
|
|
||||||
public void onCameraStart()
|
|
||||||
{
|
|
||||||
if (camera_service_running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mCamera != null)
|
|
||||||
mCamera.startPreview();
|
|
||||||
camera_service_running = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executed when the {@link Camera} is done capturing.
|
|
||||||
* <p>
|
|
||||||
* Note that this does not release the currently held
|
|
||||||
* {@link Camera} instance and must be freed by calling
|
|
||||||
* {@link #onCameraFree}
|
|
||||||
*/
|
|
||||||
public void onCameraStop()
|
|
||||||
{
|
|
||||||
if (!camera_service_running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (mCamera != null)
|
|
||||||
mCamera.stopPreview();
|
|
||||||
camera_service_running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Releases the currently held {@link Camera} instance.
|
|
||||||
*/
|
|
||||||
public void onCameraFree()
|
|
||||||
{
|
|
||||||
onCameraStop();
|
|
||||||
|
|
||||||
if (mCamera != null)
|
|
||||||
mCamera.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the camera for use.
|
|
||||||
*/
|
|
||||||
public void onCameraInit()
|
|
||||||
{
|
|
||||||
if (mCamera != null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mCamera = Camera.open();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Polls the camera for updates to the {@link SurfaceTexture}.
|
|
||||||
*
|
|
||||||
* @return true if polling was successful, false otherwise.
|
|
||||||
*/
|
|
||||||
public boolean onCameraPoll()
|
|
||||||
{
|
|
||||||
if (!camera_service_running)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (texture == null)
|
|
||||||
{
|
|
||||||
Log.i("RetroActivity", "No texture");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
|
|
||||||
{
|
|
||||||
if (updateSurface)
|
|
||||||
{
|
|
||||||
texture.updateTexImage();
|
|
||||||
}
|
|
||||||
|
|
||||||
long newTimestamp = texture.getTimestamp();
|
|
||||||
|
|
||||||
if (newTimestamp != lastTimestamp)
|
|
||||||
{
|
|
||||||
lastTimestamp = newTimestamp;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the {@link SurfaceTexture} used by the
|
|
||||||
* {@link Camera} with a given OpenGL texure ID.
|
|
||||||
*
|
|
||||||
* @param gl_texid texture ID to initialize the
|
|
||||||
* {@link SurfaceTexture} with.
|
|
||||||
*/
|
|
||||||
public void onCameraTextureInit(int gl_texid)
|
|
||||||
{
|
|
||||||
texture = new SurfaceTexture(gl_texid);
|
|
||||||
texture.setOnFrameAvailableListener(onCameraFrameAvailableListener);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the {@link Camera} texture with the texture represented
|
|
||||||
* by the given OpenGL texture ID.
|
|
||||||
*
|
|
||||||
* @param gl_texid The texture ID representing the texture to set the camera to.
|
|
||||||
* @throws IOException If setting the texture fails.
|
|
||||||
*/
|
|
||||||
public void onCameraSetTexture(int gl_texid) throws IOException
|
|
||||||
{
|
|
||||||
if (texture == null)
|
|
||||||
onCameraTextureInit(gl_texid);
|
|
||||||
|
|
||||||
if (mCamera != null)
|
|
||||||
mCamera.setPreviewTexture(texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final OnFrameAvailableListener onCameraFrameAvailableListener = new OnFrameAvailableListener()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void onFrameAvailable(SurfaceTexture surfaceTexture)
|
|
||||||
{
|
|
||||||
updateSurface = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate(Bundle savedInstanceState)
|
|
||||||
{
|
|
||||||
// Save the current setting for updates
|
|
||||||
SharedPreferences prefs = UserPreferences.getPreferences(this);
|
|
||||||
SharedPreferences.Editor edit = prefs.edit();
|
|
||||||
edit.putBoolean("CAMERA_UPDATES_ON", false);
|
|
||||||
edit.apply();
|
|
||||||
|
|
||||||
camera_service_running = false;
|
|
||||||
|
|
||||||
super.onCreate(savedInstanceState);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause()
|
|
||||||
{
|
|
||||||
// Save the current setting for updates
|
|
||||||
SharedPreferences prefs = UserPreferences.getPreferences(this);
|
|
||||||
SharedPreferences.Editor edit = prefs.edit();
|
|
||||||
edit.putBoolean("CAMERA_UPDATES_ON", camera_service_running);
|
|
||||||
edit.apply();
|
|
||||||
|
|
||||||
onCameraStop();
|
|
||||||
super.onPause();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume()
|
|
||||||
{
|
|
||||||
SharedPreferences prefs = UserPreferences.getPreferences(this);
|
|
||||||
SharedPreferences.Editor edit = prefs.edit();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get any previous setting for camera updates
|
|
||||||
* Gets "false" if an error occurs
|
|
||||||
*/
|
|
||||||
if (prefs.contains("CAMERA_UPDATES_ON"))
|
|
||||||
{
|
|
||||||
camera_service_running = prefs.getBoolean("CAMERA_UPDATES_ON", false);
|
|
||||||
if (camera_service_running)
|
|
||||||
{
|
|
||||||
onCameraStart();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // Otherwise, turn off camera updates
|
|
||||||
{
|
|
||||||
edit.putBoolean("CAMERA_UPDATES_ON", false);
|
|
||||||
edit.apply();
|
|
||||||
camera_service_running = false;
|
|
||||||
}
|
|
||||||
super.onResume();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy()
|
|
||||||
{
|
|
||||||
onCameraFree();
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStop()
|
|
||||||
{
|
|
||||||
onCameraStop();
|
|
||||||
super.onStop();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,141 +0,0 @@
|
||||||
package com.retroarch.browser.retroactivity;
|
|
||||||
|
|
||||||
import com.retroarch.browser.preferences.util.UserPreferences;
|
|
||||||
import android.annotation.TargetApi;
|
|
||||||
import android.content.res.Configuration;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.IntentFilter;
|
|
||||||
import android.app.UiModeManager;
|
|
||||||
import android.os.BatteryManager;
|
|
||||||
import android.os.Build;
|
|
||||||
import android.os.PowerManager;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class which provides common methods for RetroActivity related classes.
|
|
||||||
*/
|
|
||||||
public class RetroActivityCommon extends RetroActivityLocation
|
|
||||||
{
|
|
||||||
public static int FRONTEND_POWERSTATE_NONE = 0;
|
|
||||||
public static int FRONTEND_POWERSTATE_NO_SOURCE = 1;
|
|
||||||
public static int FRONTEND_POWERSTATE_CHARGING = 2;
|
|
||||||
public static int FRONTEND_POWERSTATE_CHARGED = 3;
|
|
||||||
public static int FRONTEND_POWERSTATE_ON_POWER_SOURCE = 4;
|
|
||||||
public boolean sustainedPerformanceMode = true;
|
|
||||||
|
|
||||||
// Exiting cleanly from NDK seems to be nearly impossible.
|
|
||||||
// Have to use exit(0) to avoid weird things happening, even with runOnUiThread() approaches.
|
|
||||||
// Use a separate JNI function to explicitly trigger the readback.
|
|
||||||
public void onRetroArchExit()
|
|
||||||
{
|
|
||||||
finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(24)
|
|
||||||
public void setSustainedPerformanceMode(boolean on)
|
|
||||||
{
|
|
||||||
sustainedPerformanceMode = on;
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 24) {
|
|
||||||
if (isSustainedPerformanceModeSupported()) {
|
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
|
||||||
|
|
||||||
runOnUiThread(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Log.i("RetroActivity", "setting sustained performance mode to " + sustainedPerformanceMode);
|
|
||||||
|
|
||||||
getWindow().setSustainedPerformanceMode(sustainedPerformanceMode);
|
|
||||||
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
latch.await();
|
|
||||||
}catch(InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(24)
|
|
||||||
public boolean isSustainedPerformanceModeSupported()
|
|
||||||
{
|
|
||||||
boolean supported = false;
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 24)
|
|
||||||
{
|
|
||||||
PowerManager powerManager = (PowerManager)getSystemService(Context.POWER_SERVICE);
|
|
||||||
|
|
||||||
if (powerManager.isSustainedPerformanceModeSupported())
|
|
||||||
supported = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Log.i("RetroActivity", "isSustainedPerformanceModeSupported? " + supported);
|
|
||||||
|
|
||||||
return supported;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBatteryLevel()
|
|
||||||
{
|
|
||||||
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
|
||||||
// This doesn't actually register anything (or need to) because we know this particular intent is sticky and we do not specify a BroadcastReceiver anyway
|
|
||||||
Intent batteryStatus = registerReceiver(null, ifilter);
|
|
||||||
int level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
|
|
||||||
int scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
|
|
||||||
|
|
||||||
float percent = ((float)level / (float)scale) * 100.0f;
|
|
||||||
|
|
||||||
Log.i("RetroActivity", "battery: level = " + level + ", scale = " + scale + ", percent = " + percent);
|
|
||||||
|
|
||||||
return (int)percent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPowerstate()
|
|
||||||
{
|
|
||||||
IntentFilter ifilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
|
||||||
// This doesn't actually register anything (or need to) because we know this particular intent is sticky and we do not specify a BroadcastReceiver anyway
|
|
||||||
Intent batteryStatus = registerReceiver(null, ifilter);
|
|
||||||
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
|
|
||||||
boolean hasBattery = batteryStatus.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false);
|
|
||||||
boolean isCharging = (status == BatteryManager.BATTERY_STATUS_CHARGING);
|
|
||||||
boolean isCharged = (status == BatteryManager.BATTERY_STATUS_FULL);
|
|
||||||
int powerstate = FRONTEND_POWERSTATE_NONE;
|
|
||||||
|
|
||||||
if (isCharged)
|
|
||||||
powerstate = FRONTEND_POWERSTATE_CHARGED;
|
|
||||||
else if (isCharging)
|
|
||||||
powerstate = FRONTEND_POWERSTATE_CHARGING;
|
|
||||||
else if (!hasBattery)
|
|
||||||
powerstate = FRONTEND_POWERSTATE_NO_SOURCE;
|
|
||||||
else
|
|
||||||
powerstate = FRONTEND_POWERSTATE_ON_POWER_SOURCE;
|
|
||||||
|
|
||||||
Log.i("RetroActivity", "power state = " + powerstate);
|
|
||||||
|
|
||||||
return powerstate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isAndroidTV()
|
|
||||||
{
|
|
||||||
Configuration config = getResources().getConfiguration();
|
|
||||||
UiModeManager uiModeManager = (UiModeManager)getSystemService(UI_MODE_SERVICE);
|
|
||||||
|
|
||||||
if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION)
|
|
||||||
{
|
|
||||||
Log.i("RetroActivity", "isAndroidTV == true");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log.i("RetroActivity", "isAndroidTV == false");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,87 +0,0 @@
|
||||||
package com.retroarch.browser.retroactivity;
|
|
||||||
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.WindowManager;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.hardware.input.InputManager;
|
|
||||||
import android.os.Build;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
public final class RetroActivityFuture extends RetroActivityCamera {
|
|
||||||
|
|
||||||
// If set to true then Retroarch will completely exit when it loses focus
|
|
||||||
private boolean quitfocus = false;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume() {
|
|
||||||
super.onResume();
|
|
||||||
|
|
||||||
setSustainedPerformanceMode(sustainedPerformanceMode);
|
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= 19) {
|
|
||||||
// Immersive mode
|
|
||||||
|
|
||||||
// Constants from API > 14
|
|
||||||
final int API_SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
|
|
||||||
final int API_SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
|
|
||||||
final int API_SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
|
|
||||||
final int API_SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
|
|
||||||
final int API_SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 0x00001000;
|
|
||||||
|
|
||||||
View thisView = getWindow().getDecorView();
|
|
||||||
thisView.setSystemUiVisibility(API_SYSTEM_UI_FLAG_LAYOUT_STABLE
|
|
||||||
| API_SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
|
||||||
| API_SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
|
||||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
|
||||||
| API_SYSTEM_UI_FLAG_FULLSCREEN
|
|
||||||
| API_SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
|
|
||||||
|
|
||||||
// Check for Android UI specific parameters
|
|
||||||
Intent retro = getIntent();
|
|
||||||
String refresh = retro.getStringExtra("REFRESH");
|
|
||||||
|
|
||||||
// If REFRESH parameter is provided then try to set refreshrate accordingly
|
|
||||||
if(refresh != null) {
|
|
||||||
WindowManager.LayoutParams params = getWindow().getAttributes();
|
|
||||||
params.preferredRefreshRate = Integer.parseInt(refresh);
|
|
||||||
getWindow().setAttributes(params);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If QUITFOCUS parameter is provided then enable that Retroarch quits when focus is lost
|
|
||||||
quitfocus = retro.hasExtra("QUITFOCUS");
|
|
||||||
|
|
||||||
// If HIDEMOUSE parameters is provided then hide the mourse cursor
|
|
||||||
// This requires NVIDIA Android extensions (available on NVIDIA Shield), if they are not
|
|
||||||
// available then nothing will be done
|
|
||||||
if (retro.hasExtra("HIDEMOUSE")) hideMouseCursor();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void hideMouseCursor() {
|
|
||||||
|
|
||||||
// Check for NVIDIA extensions and minimum SDK version
|
|
||||||
Method mInputManager_setCursorVisibility;
|
|
||||||
try { mInputManager_setCursorVisibility =
|
|
||||||
InputManager.class.getMethod("setCursorVisibility", boolean.class);
|
|
||||||
}
|
|
||||||
catch (NoSuchMethodException ex) {
|
|
||||||
return; // Extensions were not available so do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide the mouse cursor
|
|
||||||
InputManager inputManager = (InputManager) getSystemService(Context.INPUT_SERVICE);
|
|
||||||
try { mInputManager_setCursorVisibility.invoke(inputManager, false); }
|
|
||||||
catch (InvocationTargetException ite) { }
|
|
||||||
catch (IllegalAccessException iae) { }
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStop() {
|
|
||||||
super.onStop();
|
|
||||||
|
|
||||||
// If QUITFOCUS parameter was set then completely exit Retroarch when focus is lost
|
|
||||||
if (quitfocus) System.exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,105 +0,0 @@
|
||||||
package com.retroarch.browser.retroactivity;
|
|
||||||
|
|
||||||
import com.retroarch.browser.mainmenu.MainMenuActivity;
|
|
||||||
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
public class RetroActivityIntent extends RetroActivityCommon {
|
|
||||||
private Intent pendingIntent = null;
|
|
||||||
private static final String TAG = "RetroArch";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBackPressed()
|
|
||||||
{
|
|
||||||
Log.i("RetroActivity", "onBackKeyPressed");
|
|
||||||
Intent retro = new Intent(this, MainMenuActivity.class);
|
|
||||||
retro.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
|
||||||
startActivity(retro);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onNewIntent(Intent intent)
|
|
||||||
{
|
|
||||||
Log.i("RetroActivity", "onNewIntent invoked.");
|
|
||||||
super.onNewIntent(intent);
|
|
||||||
setIntent(intent);
|
|
||||||
pendingIntent = intent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the ROM file specified in the pending intent.
|
|
||||||
*
|
|
||||||
* @return the ROM file specified in the pending intent.
|
|
||||||
*/
|
|
||||||
public String getPendingIntentFullPath()
|
|
||||||
{
|
|
||||||
return pendingIntent.getStringExtra("ROM");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the specified path to the libretro core in the pending intent.
|
|
||||||
*
|
|
||||||
* @return the specified path to the libretro core in the pending intent.
|
|
||||||
*/
|
|
||||||
public String getPendingIntentLibretroPath()
|
|
||||||
{
|
|
||||||
return pendingIntent.getStringExtra("LIBRETRO");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the path specified in the pending intent to the retroarch cfg file.
|
|
||||||
*
|
|
||||||
* @return the path specified in the pending intent to the retroarch cfg file.
|
|
||||||
*/
|
|
||||||
public String getPendingIntentConfigPath()
|
|
||||||
{
|
|
||||||
return pendingIntent.getStringExtra("CONFIGFILE");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPendingIntentStorageLocation()
|
|
||||||
{
|
|
||||||
return pendingIntent.getStringExtra("SDCARD");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPendingIntentDownloadLocation()
|
|
||||||
{
|
|
||||||
return pendingIntent.getStringExtra("DOWNLOADS");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPendingIntentScreenshotsLocation()
|
|
||||||
{
|
|
||||||
return pendingIntent.getStringExtra("SCREENSHOTS");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the specified IME in the pending intent.
|
|
||||||
*
|
|
||||||
* @return the specified IME in the pending intent.
|
|
||||||
*/
|
|
||||||
public String getPendingIntentIME()
|
|
||||||
{
|
|
||||||
return pendingIntent.getStringExtra("IME");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether or not a pending intent exists.
|
|
||||||
*
|
|
||||||
* @return true if a pending intent exists, false otherwise.
|
|
||||||
*/
|
|
||||||
public boolean hasPendingIntent()
|
|
||||||
{
|
|
||||||
if (pendingIntent == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clears the current pending intent.
|
|
||||||
*/
|
|
||||||
public void clearPendingIntent()
|
|
||||||
{
|
|
||||||
pendingIntent = null;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,316 +0,0 @@
|
||||||
package com.retroarch.browser.retroactivity;
|
|
||||||
|
|
||||||
import com.google.android.gms.common.ConnectionResult;
|
|
||||||
import com.google.android.gms.common.GooglePlayServicesClient.ConnectionCallbacks;
|
|
||||||
import com.google.android.gms.common.GooglePlayServicesClient.OnConnectionFailedListener;
|
|
||||||
import com.google.android.gms.location.LocationClient;
|
|
||||||
import com.google.android.gms.location.LocationListener;
|
|
||||||
import com.google.android.gms.location.LocationRequest;
|
|
||||||
import com.retroarch.browser.preferences.util.UserPreferences;
|
|
||||||
|
|
||||||
import android.app.NativeActivity;
|
|
||||||
import android.content.IntentSender;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.location.Location;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class that implements location-based functionality for
|
|
||||||
* the {@link RetroActivityFuture} and {@link RetroActivityPast}
|
|
||||||
* activities.
|
|
||||||
*/
|
|
||||||
public class RetroActivityLocation extends NativeActivity
|
|
||||||
implements ConnectionCallbacks, OnConnectionFailedListener, LocationListener
|
|
||||||
{
|
|
||||||
/* LOCATION VARIABLES */
|
|
||||||
private static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 0;
|
|
||||||
private LocationClient mLocationClient = null;
|
|
||||||
private Location mCurrentLocation;
|
|
||||||
|
|
||||||
// Define an object that holds accuracy and frequency parameters
|
|
||||||
LocationRequest mLocationRequest = null;
|
|
||||||
boolean mUpdatesRequested = false;
|
|
||||||
boolean locationChanged = false;
|
|
||||||
boolean location_service_running = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by Location Services when the request to connect the
|
|
||||||
* client finishes successfully. At this point, you can
|
|
||||||
* request the current location or start periodic updates
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onConnected(Bundle dataBundle)
|
|
||||||
{
|
|
||||||
if (mLocationClient == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Display the connection status
|
|
||||||
Toast.makeText(this, "Connected", Toast.LENGTH_SHORT).show();
|
|
||||||
location_service_running = true;
|
|
||||||
|
|
||||||
// If already requested, start periodic updates
|
|
||||||
if (mUpdatesRequested)
|
|
||||||
{
|
|
||||||
mLocationClient.requestLocationUpdates(mLocationRequest, this, null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Get last known location
|
|
||||||
mCurrentLocation = mLocationClient.getLastLocation();
|
|
||||||
locationChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by Location Services if the connection to the
|
|
||||||
* location client drops because of an error.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onDisconnected()
|
|
||||||
{
|
|
||||||
if (mLocationClient == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Display the connection status
|
|
||||||
Toast.makeText(this, "Disconnected. Please re-connect.", Toast.LENGTH_SHORT).show();
|
|
||||||
|
|
||||||
// If the client is connected
|
|
||||||
if (mLocationClient.isConnected())
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Remove location updates for a listener.
|
|
||||||
* The current Activity is the listener, so
|
|
||||||
* the argument is "this".
|
|
||||||
*/
|
|
||||||
mLocationClient.removeLocationUpdates(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
location_service_running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called by Location Services if the attempt to
|
|
||||||
* Location Services fails.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void onConnectionFailed(ConnectionResult connectionResult)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Google Play services can resolve some errors it detects.
|
|
||||||
* If the error has a resolution, try sending an Intent to
|
|
||||||
* start a Google Play services activity that can resolve
|
|
||||||
* error.
|
|
||||||
*/
|
|
||||||
if (connectionResult.hasResolution())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Start an Activity that tries to resolve the error
|
|
||||||
connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
|
|
||||||
}
|
|
||||||
catch (IntentSender.SendIntentException e)
|
|
||||||
{
|
|
||||||
// Thrown if Google Play services cancelled the original PendingIntent
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* If no resolution is available, display a dialog to the
|
|
||||||
* user with the error.
|
|
||||||
*/
|
|
||||||
Log.e("Connection failed", "error code: " + connectionResult.getErrorCode());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the update interval at which location-based updates
|
|
||||||
* should occur
|
|
||||||
*/
|
|
||||||
public void onLocationSetInterval(int update_interval_in_ms, int distance_interval)
|
|
||||||
{
|
|
||||||
// Use high accuracy
|
|
||||||
if (mLocationRequest == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
|
|
||||||
|
|
||||||
if (update_interval_in_ms == 0)
|
|
||||||
mLocationRequest.setInterval(5 * 1000); // 5 seconds
|
|
||||||
else
|
|
||||||
mLocationRequest.setInterval(update_interval_in_ms);
|
|
||||||
|
|
||||||
// Set the fastest update interval to 1 second
|
|
||||||
mLocationRequest.setFastestInterval(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializing methods for location based functionality.
|
|
||||||
*/
|
|
||||||
public void onLocationInit()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Create a new location client, using the enclosing class to
|
|
||||||
* handle callbacks.
|
|
||||||
*/
|
|
||||||
if (mLocationClient == null)
|
|
||||||
mLocationClient = new LocationClient(this, this, this);
|
|
||||||
|
|
||||||
// Start with updates turned off
|
|
||||||
mUpdatesRequested = false;
|
|
||||||
|
|
||||||
// Create the LocationRequest object
|
|
||||||
if (mLocationRequest == null)
|
|
||||||
mLocationRequest = LocationRequest.create();
|
|
||||||
|
|
||||||
onLocationSetInterval(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executed upon starting the {@link LocationClient}.
|
|
||||||
*/
|
|
||||||
public void onLocationStart()
|
|
||||||
{
|
|
||||||
if (mLocationClient == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
mUpdatesRequested = true;
|
|
||||||
|
|
||||||
// Connect the client.
|
|
||||||
mLocationClient.connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Free up location services resources.
|
|
||||||
*/
|
|
||||||
public void onLocationFree()
|
|
||||||
{
|
|
||||||
/* TODO/FIXME */
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Executed upon stopping the location client.
|
|
||||||
* Does nothing if called when the client is not started.
|
|
||||||
*/
|
|
||||||
public void onLocationStop()
|
|
||||||
{
|
|
||||||
// Disconnecting the client invalidates it.
|
|
||||||
if (mLocationClient != null && mUpdatesRequested)
|
|
||||||
mLocationClient.disconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the latitude at the current location in degrees.
|
|
||||||
*
|
|
||||||
* @return the latitude at the current location.
|
|
||||||
*/
|
|
||||||
public double onLocationGetLatitude()
|
|
||||||
{
|
|
||||||
return mCurrentLocation.getLatitude();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the longitude at the current location in degrees.
|
|
||||||
*
|
|
||||||
* @return the longitude at the current location.
|
|
||||||
*/
|
|
||||||
public double onLocationGetLongitude()
|
|
||||||
{
|
|
||||||
return mCurrentLocation.getLongitude();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the horizontal accuracy of the current location
|
|
||||||
* in meters. (NOTE: There seems to be no vertical accuracy
|
|
||||||
* for a given location with the Android location API)
|
|
||||||
*
|
|
||||||
* @return the horizontal accuracy of the current position.
|
|
||||||
*/
|
|
||||||
public double onLocationGetHorizontalAccuracy()
|
|
||||||
{
|
|
||||||
return mCurrentLocation.getAccuracy();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tells us whether the location listener callback has
|
|
||||||
* updated the current location since the last time
|
|
||||||
* we polled.
|
|
||||||
*
|
|
||||||
* @return true if location has changed, false if location has not changed.
|
|
||||||
*/
|
|
||||||
public boolean onLocationHasChanged()
|
|
||||||
{
|
|
||||||
boolean hasChanged = locationChanged;
|
|
||||||
|
|
||||||
// Reset flag
|
|
||||||
if (hasChanged)
|
|
||||||
locationChanged = false;
|
|
||||||
|
|
||||||
return hasChanged;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define the callback method that receives location updates
|
|
||||||
@Override
|
|
||||||
public void onLocationChanged(Location location)
|
|
||||||
{
|
|
||||||
if (!location_service_running)
|
|
||||||
return;
|
|
||||||
|
|
||||||
locationChanged = true;
|
|
||||||
mCurrentLocation = location;
|
|
||||||
|
|
||||||
// Report to the UI that the location was updated
|
|
||||||
String msg = "Updated Location: " + location.getLatitude() + ", " + location.getLongitude();
|
|
||||||
Log.i("RetroArch GPS", msg);
|
|
||||||
//Toast.makeText(this, msg, Toast.LENGTH_SHORT).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPause()
|
|
||||||
{
|
|
||||||
// Save the current setting for updates
|
|
||||||
SharedPreferences prefs = UserPreferences.getPreferences(this);
|
|
||||||
SharedPreferences.Editor edit = prefs.edit();
|
|
||||||
edit.putBoolean("LOCATION_UPDATES_ON", mUpdatesRequested);
|
|
||||||
edit.apply();
|
|
||||||
|
|
||||||
super.onPause();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onResume()
|
|
||||||
{
|
|
||||||
SharedPreferences prefs = UserPreferences.getPreferences(this);
|
|
||||||
SharedPreferences.Editor edit = prefs.edit();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get any previous setting for location updates
|
|
||||||
* Gets "false" if an error occurs
|
|
||||||
*/
|
|
||||||
if (prefs.contains("LOCATION_UPDATES_ON"))
|
|
||||||
{
|
|
||||||
mUpdatesRequested = prefs.getBoolean("LOCATION_UPDATES_ON", false);
|
|
||||||
if (mUpdatesRequested)
|
|
||||||
location_service_running = true;
|
|
||||||
}
|
|
||||||
else // Otherwise, turn off location updates
|
|
||||||
{
|
|
||||||
edit.putBoolean("LOCATION_UPDATES_ON", false);
|
|
||||||
edit.apply();
|
|
||||||
location_service_running = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
super.onResume();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onStop()
|
|
||||||
{
|
|
||||||
onLocationStop();
|
|
||||||
super.onStop();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
package com.retroarch.browser.retroactivity;
|
|
||||||
|
|
||||||
// For Android 2.3.x
|
|
||||||
|
|
||||||
public final class RetroActivityPast extends RetroActivityCommon
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -1569,6 +1569,10 @@ end:
|
||||||
free(content_ctx.name_ups);
|
free(content_ctx.name_ups);
|
||||||
if (content_ctx.directory_system)
|
if (content_ctx.directory_system)
|
||||||
free(content_ctx.directory_system);
|
free(content_ctx.directory_system);
|
||||||
|
if (content_ctx.directory_cache)
|
||||||
|
free(content_ctx.directory_cache);
|
||||||
|
if (content_ctx.valid_extensions)
|
||||||
|
free(content_ctx.valid_extensions);
|
||||||
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
{
|
{
|
||||||
|
@ -1772,10 +1776,13 @@ void content_set_subsystem(unsigned idx)
|
||||||
|
|
||||||
pending_subsystem_id = idx;
|
pending_subsystem_id = idx;
|
||||||
|
|
||||||
strlcpy(pending_subsystem_ident,
|
if (subsystem)
|
||||||
subsystem->ident, sizeof(pending_subsystem_ident));
|
{
|
||||||
|
strlcpy(pending_subsystem_ident,
|
||||||
|
subsystem->ident, sizeof(pending_subsystem_ident));
|
||||||
|
|
||||||
pending_subsystem_rom_num = subsystem->num_roms;
|
pending_subsystem_rom_num = subsystem->num_roms;
|
||||||
|
}
|
||||||
|
|
||||||
RARCH_LOG("[subsystem] settings current subsytem to: %d(%s) roms: %d\n",
|
RARCH_LOG("[subsystem] settings current subsytem to: %d(%s) roms: %d\n",
|
||||||
pending_subsystem_id, pending_subsystem_ident, pending_subsystem_rom_num);
|
pending_subsystem_id, pending_subsystem_ident, pending_subsystem_rom_num);
|
||||||
|
|
|
@ -6,7 +6,18 @@
|
||||||
#include <QStyleOption>
|
#include <QStyleOption>
|
||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QAction>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
#include "filedropwidget.h"
|
#include "filedropwidget.h"
|
||||||
|
#include "playlistentrydialog.h"
|
||||||
|
#include "../ui_qt.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "../../../file_path_special.h"
|
||||||
|
}
|
||||||
|
|
||||||
FileDropWidget::FileDropWidget(QWidget *parent) :
|
FileDropWidget::FileDropWidget(QWidget *parent) :
|
||||||
QWidget(parent)
|
QWidget(parent)
|
||||||
|
@ -67,3 +78,101 @@ void FileDropWidget::dropEvent(QDropEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onFileDropWidgetContextMenuRequested(const QPoint &pos)
|
||||||
|
{
|
||||||
|
QScopedPointer<QMenu> menu;
|
||||||
|
QScopedPointer<QAction> addEntryAction;
|
||||||
|
QScopedPointer<QAction> addFilesAction;
|
||||||
|
QScopedPointer<QAction> addFolderAction;
|
||||||
|
QScopedPointer<QAction> editAction;
|
||||||
|
QScopedPointer<QAction> deleteAction;
|
||||||
|
QPointer<QAction> selectedAction;
|
||||||
|
QPoint cursorPos = QCursor::pos();
|
||||||
|
QHash<QString, QString> contentHash = getCurrentContentHash();
|
||||||
|
|
||||||
|
menu.reset(new QMenu(this));
|
||||||
|
|
||||||
|
addEntryAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ADD_ENTRY)), this));
|
||||||
|
addFilesAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ADD_FILES)), this));
|
||||||
|
addFolderAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ADD_FOLDER)), this));
|
||||||
|
editAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_EDIT)), this));
|
||||||
|
deleteAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_DELETE)), this));
|
||||||
|
|
||||||
|
menu->addAction(addEntryAction.data());
|
||||||
|
menu->addAction(addFilesAction.data());
|
||||||
|
menu->addAction(addFolderAction.data());
|
||||||
|
|
||||||
|
if (!contentHash.isEmpty())
|
||||||
|
{
|
||||||
|
menu->addAction(editAction.data());
|
||||||
|
menu->addAction(deleteAction.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
selectedAction = menu->exec(cursorPos);
|
||||||
|
|
||||||
|
if (!selectedAction)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (selectedAction == addFilesAction.data())
|
||||||
|
{
|
||||||
|
QStringList filePaths = QFileDialog::getOpenFileNames(this, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_SELECT_FILES));
|
||||||
|
|
||||||
|
if (!filePaths.isEmpty())
|
||||||
|
addFilesToPlaylist(filePaths);
|
||||||
|
}
|
||||||
|
else if (selectedAction == addEntryAction.data())
|
||||||
|
{
|
||||||
|
addFilesToPlaylist(QStringList());
|
||||||
|
}
|
||||||
|
else if (selectedAction == addFolderAction.data())
|
||||||
|
{
|
||||||
|
QString dirPath = QFileDialog::getExistingDirectory(this, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_SELECT_FOLDER), QString(), QFileDialog::ShowDirsOnly);
|
||||||
|
|
||||||
|
if (!dirPath.isEmpty())
|
||||||
|
addFilesToPlaylist(QStringList() << dirPath);
|
||||||
|
}
|
||||||
|
else if (selectedAction == editAction.data())
|
||||||
|
{
|
||||||
|
PlaylistEntryDialog *playlistDialog = playlistEntryDialog();
|
||||||
|
QHash<QString, QString> selectedCore;
|
||||||
|
QString selectedDatabase;
|
||||||
|
QString selectedName;
|
||||||
|
QString selectedPath;
|
||||||
|
QString currentPlaylistPath = getCurrentPlaylistPath();
|
||||||
|
|
||||||
|
if (!playlistDialog->showDialog(contentHash))
|
||||||
|
return;
|
||||||
|
|
||||||
|
selectedName = m_playlistEntryDialog->getSelectedName();
|
||||||
|
selectedPath = m_playlistEntryDialog->getSelectedPath();
|
||||||
|
selectedCore = m_playlistEntryDialog->getSelectedCore();
|
||||||
|
selectedDatabase = m_playlistEntryDialog->getSelectedDatabase();
|
||||||
|
|
||||||
|
if (selectedCore.isEmpty())
|
||||||
|
{
|
||||||
|
selectedCore["core_name"] = "DETECT";
|
||||||
|
selectedCore["core_path"] = "DETECT";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedDatabase.isEmpty())
|
||||||
|
{
|
||||||
|
selectedDatabase = QFileInfo(currentPlaylistPath).fileName().remove(file_path_str(FILE_PATH_LPL_EXTENSION));
|
||||||
|
}
|
||||||
|
|
||||||
|
contentHash["label"] = selectedName;
|
||||||
|
contentHash["path"] = selectedPath;
|
||||||
|
contentHash["core_name"] = selectedCore.value("core_name");
|
||||||
|
contentHash["core_path"] = selectedCore.value("core_path");
|
||||||
|
contentHash["db_name"] = selectedDatabase;
|
||||||
|
|
||||||
|
if (!updateCurrentPlaylistEntry(contentHash))
|
||||||
|
{
|
||||||
|
showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_UPDATE_PLAYLIST_ENTRY), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (selectedAction == deleteAction.data())
|
||||||
|
{
|
||||||
|
deleteCurrentPlaylistItem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -559,7 +559,7 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&)
|
||||||
strlcpy(settings->arrays.playlist_cores,
|
strlcpy(settings->arrays.playlist_cores,
|
||||||
new_playlist_cores, sizeof(settings->arrays.playlist_cores));
|
new_playlist_cores, sizeof(settings->arrays.playlist_cores));
|
||||||
}
|
}
|
||||||
else if (selectedAction == deletePlaylistAction.data())
|
else if (selectedItem && selectedAction == deletePlaylistAction.data())
|
||||||
{
|
{
|
||||||
if (currentPlaylistFile.exists())
|
if (currentPlaylistFile.exists())
|
||||||
{
|
{
|
||||||
|
@ -583,7 +583,7 @@ void MainWindow::onPlaylistWidgetContextMenuRequested(const QPoint&)
|
||||||
|
|
||||||
reloadPlaylists();
|
reloadPlaylists();
|
||||||
}
|
}
|
||||||
else if (selectedAction == hideAction.data())
|
else if (selectedItem && selectedAction == hideAction.data())
|
||||||
{
|
{
|
||||||
int row = m_listWidget->row(selectedItem);
|
int row = m_listWidget->row(selectedItem);
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,46 @@
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
#include <QResizeEvent>
|
#include <QResizeEvent>
|
||||||
|
#include <QScrollArea>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QGroupBox>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QFormLayout>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QDoubleSpinBox>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QComboBox>
|
||||||
|
|
||||||
#include "shaderparamsdialog.h"
|
#include "shaderparamsdialog.h"
|
||||||
|
#include "../ui_qt.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
#include "../../../command.h"
|
||||||
|
#ifdef HAVE_MENU
|
||||||
|
#include "../../../menu/menu_shader.h"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
ShaderParamsDialog::ShaderParamsDialog(QWidget *parent) :
|
ShaderParamsDialog::ShaderParamsDialog(QWidget *parent) :
|
||||||
QDialog(parent)
|
QDialog(parent)
|
||||||
|
,m_layout(NULL)
|
||||||
{
|
{
|
||||||
|
QScrollArea *scrollArea = NULL;
|
||||||
|
QWidget *widget = NULL;
|
||||||
|
|
||||||
|
setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER_OPTIONS));
|
||||||
|
setObjectName("shaderParamsDialog");
|
||||||
|
|
||||||
|
m_layout = new QVBoxLayout();
|
||||||
|
|
||||||
|
widget = new QWidget();
|
||||||
|
widget->setLayout(m_layout);
|
||||||
|
widget->setObjectName("shaderParamsWidget");
|
||||||
|
scrollArea = new QScrollArea(this);
|
||||||
|
scrollArea->setWidgetResizable(true);
|
||||||
|
scrollArea->setWidget(widget);
|
||||||
|
scrollArea->setObjectName("shaderParamsScrollArea");
|
||||||
|
|
||||||
|
setProperty("scrollArea", QVariant::fromValue(scrollArea));
|
||||||
}
|
}
|
||||||
|
|
||||||
ShaderParamsDialog::~ShaderParamsDialog()
|
ShaderParamsDialog::~ShaderParamsDialog()
|
||||||
|
@ -13,9 +49,20 @@ ShaderParamsDialog::~ShaderParamsDialog()
|
||||||
|
|
||||||
void ShaderParamsDialog::resizeEvent(QResizeEvent *event)
|
void ShaderParamsDialog::resizeEvent(QResizeEvent *event)
|
||||||
{
|
{
|
||||||
|
QVariant scrollAreaVariant = property("scrollArea");
|
||||||
|
QScrollArea *scrollArea = NULL;
|
||||||
|
|
||||||
QDialog::resizeEvent(event);
|
QDialog::resizeEvent(event);
|
||||||
|
|
||||||
emit resized(event->size());
|
if (!scrollAreaVariant.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
scrollArea = scrollAreaVariant.value<QScrollArea*>();
|
||||||
|
|
||||||
|
if (!scrollArea)
|
||||||
|
return;
|
||||||
|
|
||||||
|
scrollArea->resize(event->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderParamsDialog::closeEvent(QCloseEvent *event)
|
void ShaderParamsDialog::closeEvent(QCloseEvent *event)
|
||||||
|
@ -25,3 +72,590 @@ void ShaderParamsDialog::closeEvent(QCloseEvent *event)
|
||||||
emit closed();
|
emit closed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ShaderParamsDialog::getFilterLabel(unsigned filter)
|
||||||
|
{
|
||||||
|
QString filterString;
|
||||||
|
|
||||||
|
switch (filter)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
filterString = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DONT_CARE);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
filterString = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_LINEAR);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
filterString = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NEAREST);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return filterString;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderParamsDialog::clearLayout(QLayout *layout)
|
||||||
|
{
|
||||||
|
QLayoutItem *child = NULL;
|
||||||
|
|
||||||
|
while (layout->count() && ((child = layout->takeAt(0)) != 0))
|
||||||
|
{
|
||||||
|
QWidget *widget = child->widget();
|
||||||
|
QLayout *childLayout = child->layout();
|
||||||
|
|
||||||
|
if (widget)
|
||||||
|
{
|
||||||
|
QLayout *widgetLayout = widget->layout();
|
||||||
|
|
||||||
|
if (widgetLayout)
|
||||||
|
clearLayout(widgetLayout);
|
||||||
|
|
||||||
|
/* deleteLater() doesn't work right for some reason here,
|
||||||
|
* so just disconnect any signals in case there are pending events,
|
||||||
|
* and delete the widget immediately.
|
||||||
|
*/
|
||||||
|
widget->disconnect();
|
||||||
|
delete widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childLayout)
|
||||||
|
clearLayout(childLayout);
|
||||||
|
|
||||||
|
delete child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderParamsDialog::getShaders(struct video_shader **menu_shader, struct video_shader **video_shader)
|
||||||
|
{
|
||||||
|
video_shader_ctx_t shader_info = {0};
|
||||||
|
#ifdef HAVE_MENU
|
||||||
|
struct video_shader *shader = menu_shader_get();
|
||||||
|
|
||||||
|
if (menu_shader)
|
||||||
|
{
|
||||||
|
if (shader)
|
||||||
|
{
|
||||||
|
*menu_shader = shader;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*menu_shader = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (video_shader)
|
||||||
|
{
|
||||||
|
if (shader)
|
||||||
|
{
|
||||||
|
*video_shader = shader_info.data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*video_shader = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (video_shader)
|
||||||
|
{
|
||||||
|
if (!video_shader_driver_get_current_shader(&shader_info))
|
||||||
|
{
|
||||||
|
*video_shader = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!shader_info.data || shader_info.data->num_parameters > GFX_MAX_PARAMETERS)
|
||||||
|
{
|
||||||
|
*video_shader = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shader_info.data)
|
||||||
|
{
|
||||||
|
*video_shader = shader_info.data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*video_shader = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderParamsDialog::onFilterComboBoxIndexChanged(int)
|
||||||
|
{
|
||||||
|
QComboBox *comboBox = qobject_cast<QComboBox*>(sender());
|
||||||
|
QVariant passVariant;
|
||||||
|
int pass = 0;
|
||||||
|
bool ok = false;
|
||||||
|
struct video_shader *menu_shader = NULL;
|
||||||
|
struct video_shader *video_shader = NULL;
|
||||||
|
|
||||||
|
getShaders(&menu_shader, &video_shader);
|
||||||
|
|
||||||
|
if (!comboBox)
|
||||||
|
return;
|
||||||
|
|
||||||
|
passVariant = comboBox->property("pass");
|
||||||
|
|
||||||
|
if (!passVariant.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
pass = passVariant.toInt(&ok);
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (menu_shader && pass >= 0 && pass < static_cast<int>(menu_shader->passes))
|
||||||
|
{
|
||||||
|
QVariant data = comboBox->currentData();
|
||||||
|
|
||||||
|
if (data.isValid())
|
||||||
|
{
|
||||||
|
unsigned filter = data.toUInt(&ok);
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
if (menu_shader)
|
||||||
|
menu_shader->pass[pass].filter = filter;
|
||||||
|
if (video_shader)
|
||||||
|
video_shader->pass[pass].filter = filter;
|
||||||
|
|
||||||
|
command_event(CMD_EVENT_SHADERS_APPLY_CHANGES, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderParamsDialog::onScaleComboBoxIndexChanged(int)
|
||||||
|
{
|
||||||
|
QComboBox *comboBox = qobject_cast<QComboBox*>(sender());
|
||||||
|
QVariant passVariant;
|
||||||
|
int pass = 0;
|
||||||
|
bool ok = false;
|
||||||
|
struct video_shader *menu_shader = NULL;
|
||||||
|
struct video_shader *video_shader = NULL;
|
||||||
|
|
||||||
|
getShaders(&menu_shader, &video_shader);
|
||||||
|
|
||||||
|
if (!comboBox)
|
||||||
|
return;
|
||||||
|
|
||||||
|
passVariant = comboBox->property("pass");
|
||||||
|
|
||||||
|
if (!passVariant.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
pass = passVariant.toInt(&ok);
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (menu_shader && pass >= 0 && pass < static_cast<int>(menu_shader->passes))
|
||||||
|
{
|
||||||
|
QVariant data = comboBox->currentData();
|
||||||
|
|
||||||
|
if (data.isValid())
|
||||||
|
{
|
||||||
|
unsigned scale = data.toUInt(&ok);
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
if (menu_shader)
|
||||||
|
{
|
||||||
|
menu_shader->pass[pass].fbo.scale_x = scale;
|
||||||
|
menu_shader->pass[pass].fbo.scale_y = scale;
|
||||||
|
menu_shader->pass[pass].fbo.valid = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (video_shader)
|
||||||
|
{
|
||||||
|
video_shader->pass[pass].fbo.scale_x = scale;
|
||||||
|
video_shader->pass[pass].fbo.scale_y = scale;
|
||||||
|
video_shader->pass[pass].fbo.valid = scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
command_event(CMD_EVENT_SHADERS_APPLY_CHANGES, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderParamsDialog::reload()
|
||||||
|
{
|
||||||
|
struct video_shader *menu_shader = NULL;
|
||||||
|
struct video_shader *video_shader = NULL;
|
||||||
|
int i;
|
||||||
|
unsigned j;
|
||||||
|
|
||||||
|
getShaders(&menu_shader, &video_shader);
|
||||||
|
|
||||||
|
/* NOTE: For some reason, menu_shader_get() returns a COPY of what get_current_shader() gives us.
|
||||||
|
* And if you want to be able to change shader settings/parameters from both the raster menu and
|
||||||
|
* Qt at the same time... you must change BOTH or one will overwrite the other.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ((video_shader && video_shader->passes == 0) || !video_shader)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
clearLayout(m_layout);
|
||||||
|
|
||||||
|
/* NOTE: We assume that parameters are always grouped in order by the pass number, e.g., all parameters for pass 0 come first, then params for pass 1, etc. */
|
||||||
|
for (i = 0; i < static_cast<int>(video_shader->passes); i++)
|
||||||
|
{
|
||||||
|
QFormLayout *form = NULL;
|
||||||
|
QGroupBox *groupBox = NULL;
|
||||||
|
QFileInfo fileInfo(video_shader->pass[i].source.path);
|
||||||
|
QString shaderBasename = fileInfo.completeBaseName();
|
||||||
|
QHBoxLayout *filterScaleHBoxLayout = NULL;
|
||||||
|
QComboBox *filterComboBox = new QComboBox();
|
||||||
|
QComboBox *scaleComboBox = new QComboBox();
|
||||||
|
unsigned j = 0;
|
||||||
|
|
||||||
|
filterComboBox->setProperty("pass", i);
|
||||||
|
scaleComboBox->setProperty("pass", i);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
QString filterLabel = getFilterLabel(j);
|
||||||
|
|
||||||
|
if (filterLabel.isEmpty())
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (j == 0)
|
||||||
|
filterLabel = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DONT_CARE);
|
||||||
|
|
||||||
|
filterComboBox->addItem(filterLabel, j);
|
||||||
|
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < 7; j++)
|
||||||
|
{
|
||||||
|
QString label;
|
||||||
|
|
||||||
|
if (j == 0)
|
||||||
|
label = msg_hash_to_str(MENU_ENUM_LABEL_VALUE_DONT_CARE);
|
||||||
|
else
|
||||||
|
label = QString::number(j) + "x";
|
||||||
|
|
||||||
|
scaleComboBox->addItem(label, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
filterComboBox->setCurrentIndex(static_cast<int>(video_shader->pass[i].filter));
|
||||||
|
scaleComboBox->setCurrentIndex(static_cast<int>(video_shader->pass[i].fbo.scale_x));
|
||||||
|
|
||||||
|
/* connect the signals only after the initial index is set */
|
||||||
|
connect(filterComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onFilterComboBoxIndexChanged(int)));
|
||||||
|
connect(scaleComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onScaleComboBoxIndexChanged(int)));
|
||||||
|
|
||||||
|
form = new QFormLayout();
|
||||||
|
groupBox = new QGroupBox(shaderBasename);
|
||||||
|
groupBox->setLayout(form);
|
||||||
|
|
||||||
|
m_layout->addWidget(groupBox);
|
||||||
|
|
||||||
|
filterScaleHBoxLayout = new QHBoxLayout();
|
||||||
|
filterScaleHBoxLayout->addWidget(new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_FILTER)));
|
||||||
|
filterScaleHBoxLayout->addWidget(filterComboBox);
|
||||||
|
filterScaleHBoxLayout->addWidget(new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SCALE)));
|
||||||
|
filterScaleHBoxLayout->addWidget(scaleComboBox);
|
||||||
|
|
||||||
|
form->addRow("", filterScaleHBoxLayout);
|
||||||
|
|
||||||
|
for (j = 0; j < video_shader->num_parameters; j++)
|
||||||
|
{
|
||||||
|
struct video_shader_parameter *param = &video_shader->parameters[j];
|
||||||
|
|
||||||
|
if (param->pass != i)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
addShaderParam(param, j, form);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));
|
||||||
|
|
||||||
|
end:
|
||||||
|
resize(720, 480);
|
||||||
|
show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderParamsDialog::addShaderParam(struct video_shader_parameter *param, int parameter, QFormLayout *form)
|
||||||
|
{
|
||||||
|
QString desc = param->desc;
|
||||||
|
|
||||||
|
if ((param->minimum == 0.0)
|
||||||
|
&& (param->maximum
|
||||||
|
== (param->minimum
|
||||||
|
+ param->step)))
|
||||||
|
{
|
||||||
|
/* option is basically a bool, so use a checkbox */
|
||||||
|
QCheckBox *checkBox = new QCheckBox(this);
|
||||||
|
checkBox->setChecked(param->current == param->maximum ? true : false);
|
||||||
|
checkBox->setProperty("pass", param->pass);
|
||||||
|
|
||||||
|
connect(checkBox, SIGNAL(clicked()), this, SLOT(onShaderParamCheckBoxClicked()));
|
||||||
|
|
||||||
|
form->addRow(desc, checkBox);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QDoubleSpinBox *doubleSpinBox = NULL;
|
||||||
|
QSpinBox *spinBox = NULL;
|
||||||
|
QHBoxLayout *box = new QHBoxLayout();
|
||||||
|
QSlider *slider = new QSlider(Qt::Horizontal, this);
|
||||||
|
double value = MainWindow::lerp(param->minimum, param->maximum, 0, 100, param->current);
|
||||||
|
double intpart = 0;
|
||||||
|
bool stepIsFractional = modf(param->step, &intpart);
|
||||||
|
|
||||||
|
slider->setRange(0, 100);
|
||||||
|
slider->setSingleStep(1);
|
||||||
|
slider->setValue(value);
|
||||||
|
slider->setProperty("param", parameter);
|
||||||
|
|
||||||
|
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(onShaderParamSliderValueChanged(int)));
|
||||||
|
|
||||||
|
box->addWidget(slider);
|
||||||
|
|
||||||
|
if (stepIsFractional)
|
||||||
|
{
|
||||||
|
doubleSpinBox = new QDoubleSpinBox(this);
|
||||||
|
doubleSpinBox->setRange(param->minimum, param->maximum);
|
||||||
|
doubleSpinBox->setSingleStep(param->step);
|
||||||
|
doubleSpinBox->setValue(param->current);
|
||||||
|
doubleSpinBox->setProperty("slider", QVariant::fromValue(slider));
|
||||||
|
slider->setProperty("doubleSpinBox", QVariant::fromValue(doubleSpinBox));
|
||||||
|
|
||||||
|
connect(doubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onShaderParamDoubleSpinBoxValueChanged(double)));
|
||||||
|
|
||||||
|
box->addWidget(doubleSpinBox);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
spinBox = new QSpinBox(this);
|
||||||
|
spinBox->setRange(param->minimum, param->maximum);
|
||||||
|
spinBox->setSingleStep(param->step);
|
||||||
|
spinBox->setValue(param->current);
|
||||||
|
spinBox->setProperty("slider", QVariant::fromValue(slider));
|
||||||
|
slider->setProperty("spinBox", QVariant::fromValue(spinBox));
|
||||||
|
|
||||||
|
connect(spinBox, SIGNAL(valueChanged(int)), this, SLOT(onShaderParamSpinBoxValueChanged(int)));
|
||||||
|
|
||||||
|
box->addWidget(spinBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
form->addRow(desc, box);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderParamsDialog::onShaderParamCheckBoxClicked()
|
||||||
|
{
|
||||||
|
QCheckBox *checkBox = qobject_cast<QCheckBox*>(sender());
|
||||||
|
QVariant paramVariant;
|
||||||
|
struct video_shader *menu_shader = NULL;
|
||||||
|
struct video_shader *video_shader = NULL;
|
||||||
|
|
||||||
|
getShaders(&menu_shader, &video_shader);
|
||||||
|
|
||||||
|
if (!checkBox)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (menu_shader && menu_shader->passes == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
paramVariant = checkBox->property("parameter");
|
||||||
|
|
||||||
|
if (paramVariant.isValid())
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
int parameter = paramVariant.toInt(&ok);
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (menu_shader)
|
||||||
|
{
|
||||||
|
struct video_shader_parameter *param = NULL;
|
||||||
|
|
||||||
|
param = &menu_shader->parameters[parameter];
|
||||||
|
|
||||||
|
if (param)
|
||||||
|
param->current = (checkBox->isChecked() ? param->maximum : param->minimum);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (video_shader)
|
||||||
|
{
|
||||||
|
struct video_shader_parameter *param = NULL;
|
||||||
|
|
||||||
|
param = &video_shader->parameters[parameter];
|
||||||
|
|
||||||
|
if (param)
|
||||||
|
param->current = (checkBox->isChecked() ? param->maximum : param->minimum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderParamsDialog::onShaderParamSliderValueChanged(int)
|
||||||
|
{
|
||||||
|
QVariant spinBoxVariant;
|
||||||
|
QVariant paramVariant;
|
||||||
|
QSlider *slider = qobject_cast<QSlider*>(sender());
|
||||||
|
struct video_shader *menu_shader = NULL;
|
||||||
|
struct video_shader *video_shader = NULL;
|
||||||
|
double newValue = 0.0;
|
||||||
|
|
||||||
|
getShaders(&menu_shader, &video_shader);
|
||||||
|
|
||||||
|
if (!slider)
|
||||||
|
return;
|
||||||
|
|
||||||
|
spinBoxVariant = slider->property("spinBox");
|
||||||
|
paramVariant = slider->property("param");
|
||||||
|
|
||||||
|
if (paramVariant.isValid())
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
int parameter = paramVariant.toInt(&ok);
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
if (menu_shader)
|
||||||
|
{
|
||||||
|
struct video_shader_parameter *param = &menu_shader->parameters[parameter];
|
||||||
|
|
||||||
|
newValue = MainWindow::lerp(0, 100, param->minimum, param->maximum, slider->value());
|
||||||
|
param->current = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (video_shader)
|
||||||
|
{
|
||||||
|
struct video_shader_parameter *param = &video_shader->parameters[parameter];
|
||||||
|
|
||||||
|
newValue = MainWindow::lerp(0, 100, param->minimum, param->maximum, slider->value());
|
||||||
|
param->current = newValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spinBoxVariant.isValid())
|
||||||
|
{
|
||||||
|
QSpinBox *spinBox = spinBoxVariant.value<QSpinBox*>();
|
||||||
|
|
||||||
|
if (!spinBox)
|
||||||
|
return;
|
||||||
|
|
||||||
|
spinBox->blockSignals(true);
|
||||||
|
spinBox->setValue(newValue);
|
||||||
|
spinBox->blockSignals(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QVariant doubleSpinBoxVariant = slider->property("doubleSpinBox");
|
||||||
|
QDoubleSpinBox *doubleSpinBox = doubleSpinBoxVariant.value<QDoubleSpinBox*>();
|
||||||
|
|
||||||
|
if (!doubleSpinBox)
|
||||||
|
return;
|
||||||
|
|
||||||
|
doubleSpinBox->blockSignals(true);
|
||||||
|
doubleSpinBox->setValue(newValue);
|
||||||
|
doubleSpinBox->blockSignals(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderParamsDialog::onShaderParamSpinBoxValueChanged(int value)
|
||||||
|
{
|
||||||
|
QSpinBox *spinBox = qobject_cast<QSpinBox*>(sender());
|
||||||
|
QVariant sliderVariant;
|
||||||
|
QVariant paramVariant;
|
||||||
|
QSlider *slider = NULL;
|
||||||
|
struct video_shader *menu_shader = NULL;
|
||||||
|
struct video_shader *video_shader = NULL;
|
||||||
|
double newValue = 0.0;
|
||||||
|
|
||||||
|
getShaders(&menu_shader, &video_shader);
|
||||||
|
|
||||||
|
if (!spinBox)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sliderVariant = spinBox->property("slider");
|
||||||
|
|
||||||
|
if (!sliderVariant.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
slider = sliderVariant.value<QSlider*>();
|
||||||
|
|
||||||
|
if (!slider)
|
||||||
|
return;
|
||||||
|
|
||||||
|
paramVariant = slider->property("param");
|
||||||
|
|
||||||
|
if (paramVariant.isValid())
|
||||||
|
{
|
||||||
|
bool ok = false;
|
||||||
|
int parameter = paramVariant.toInt(&ok);
|
||||||
|
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
if (menu_shader)
|
||||||
|
{
|
||||||
|
struct video_shader_parameter *param = &menu_shader->parameters[parameter];
|
||||||
|
|
||||||
|
param->current = value;
|
||||||
|
newValue = MainWindow::lerp(param->minimum, param->maximum, 0, 100, param->current);
|
||||||
|
slider->blockSignals(true);
|
||||||
|
slider->setValue(newValue);
|
||||||
|
slider->blockSignals(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (video_shader)
|
||||||
|
{
|
||||||
|
struct video_shader_parameter *param = &video_shader->parameters[parameter];
|
||||||
|
|
||||||
|
param->current = value;
|
||||||
|
newValue = MainWindow::lerp(param->minimum, param->maximum, 0, 100, param->current);
|
||||||
|
slider->blockSignals(true);
|
||||||
|
slider->setValue(newValue);
|
||||||
|
slider->blockSignals(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderParamsDialog::onShaderParamDoubleSpinBoxValueChanged(double value)
|
||||||
|
{
|
||||||
|
QDoubleSpinBox *doubleSpinBox = qobject_cast<QDoubleSpinBox*>(sender());
|
||||||
|
QVariant sliderVariant;
|
||||||
|
QVariant paramVariant;
|
||||||
|
QSlider *slider = NULL;
|
||||||
|
struct video_shader_parameter *param = NULL;
|
||||||
|
double newValue = 0.0;
|
||||||
|
|
||||||
|
if (!doubleSpinBox)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sliderVariant = doubleSpinBox->property("slider");
|
||||||
|
|
||||||
|
if (!sliderVariant.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
slider = sliderVariant.value<QSlider*>();
|
||||||
|
|
||||||
|
if (!slider)
|
||||||
|
return;
|
||||||
|
|
||||||
|
paramVariant = slider->property("param");
|
||||||
|
|
||||||
|
if (paramVariant.isValid())
|
||||||
|
{
|
||||||
|
param = paramVariant.value<struct video_shader_parameter*>();
|
||||||
|
|
||||||
|
if (param)
|
||||||
|
{
|
||||||
|
param->current = value;
|
||||||
|
newValue = MainWindow::lerp(param->minimum, param->maximum, 0, 100, param->current);
|
||||||
|
slider->blockSignals(true);
|
||||||
|
slider->setValue(newValue);
|
||||||
|
slider->blockSignals(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
|
|
||||||
class QCloseEvent;
|
class QCloseEvent;
|
||||||
class QResizeEvent;
|
class QResizeEvent;
|
||||||
|
class QVBoxLayout;
|
||||||
|
class QFormLayout;
|
||||||
|
class QLayout;
|
||||||
|
|
||||||
class ShaderParamsDialog : public QDialog
|
class ShaderParamsDialog : public QDialog
|
||||||
{
|
{
|
||||||
|
@ -15,6 +18,22 @@ public:
|
||||||
signals:
|
signals:
|
||||||
void closed();
|
void closed();
|
||||||
void resized(QSize size);
|
void resized(QSize size);
|
||||||
|
public slots:
|
||||||
|
void reload();
|
||||||
|
private slots:
|
||||||
|
void onShaderParamCheckBoxClicked();
|
||||||
|
void onShaderParamSliderValueChanged(int value);
|
||||||
|
void onShaderParamSpinBoxValueChanged(int value);
|
||||||
|
void onShaderParamDoubleSpinBoxValueChanged(double value);
|
||||||
|
void onFilterComboBoxIndexChanged(int index);
|
||||||
|
void onScaleComboBoxIndexChanged(int index);
|
||||||
|
private:
|
||||||
|
QString getFilterLabel(unsigned filter);
|
||||||
|
void addShaderParam(struct video_shader_parameter *param, int parameter, QFormLayout *form);
|
||||||
|
void clearLayout(QLayout *layout);
|
||||||
|
void getShaders(struct video_shader **menu_shader, struct video_shader **video_shader);
|
||||||
|
|
||||||
|
QVBoxLayout *m_layout;
|
||||||
protected:
|
protected:
|
||||||
void closeEvent(QCloseEvent *event);
|
void closeEvent(QCloseEvent *event);
|
||||||
void resizeEvent(QResizeEvent *event);
|
void resizeEvent(QResizeEvent *event);
|
||||||
|
|
|
@ -314,7 +314,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||||
,m_allPlaylistsGridMaxCount(0)
|
,m_allPlaylistsGridMaxCount(0)
|
||||||
,m_playlistEntryDialog(NULL)
|
,m_playlistEntryDialog(NULL)
|
||||||
,m_statusMessageElapsedTimer()
|
,m_statusMessageElapsedTimer()
|
||||||
,m_shaderParamsDialog()
|
,m_shaderParamsDialog(new ShaderParamsDialog())
|
||||||
,m_networkManager(new QNetworkAccessManager(this))
|
,m_networkManager(new QNetworkAccessManager(this))
|
||||||
,m_updateProgressDialog(new QProgressDialog())
|
,m_updateProgressDialog(new QProgressDialog())
|
||||||
,m_updateFile()
|
,m_updateFile()
|
||||||
|
@ -585,312 +585,6 @@ double MainWindow::lerp(double x, double y, double a, double b, double d) {
|
||||||
return a + (b - a) * ((double)(d - x) / (double)(y - x));
|
return a + (b - a) * ((double)(d - x) / (double)(y - x));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onShaderParamsDialogResized(QSize size)
|
|
||||||
{
|
|
||||||
QVariant scrollAreaVariant = m_shaderParamsDialog->property("scrollArea");
|
|
||||||
QScrollArea *scrollArea = NULL;
|
|
||||||
|
|
||||||
if (!scrollAreaVariant.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
scrollArea = scrollAreaVariant.value<QScrollArea*>();
|
|
||||||
|
|
||||||
if (!scrollArea)
|
|
||||||
return;
|
|
||||||
|
|
||||||
scrollArea->resize(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onShaderParamsClicked()
|
|
||||||
{
|
|
||||||
video_shader_ctx_t shader_info = {0};
|
|
||||||
unsigned i;
|
|
||||||
int last_pass = -1;
|
|
||||||
QFormLayout *last_form = NULL;
|
|
||||||
QGroupBox *last_group = NULL;
|
|
||||||
QScrollArea *scrollArea = NULL;
|
|
||||||
QWidget *widget = NULL;
|
|
||||||
QVBoxLayout *layout = NULL;
|
|
||||||
|
|
||||||
if (!video_shader_driver_get_current_shader(&shader_info))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!shader_info.data || shader_info.data->num_parameters > GFX_MAX_PARAMETERS)
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* shader might have changed, so re-create the entire window */
|
|
||||||
if (m_shaderParamsDialog)
|
|
||||||
delete m_shaderParamsDialog;
|
|
||||||
|
|
||||||
m_shaderParamsDialog = new ShaderParamsDialog();
|
|
||||||
m_shaderParamsDialog->setWindowTitle(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PARAMETERS));
|
|
||||||
m_shaderParamsDialog->setObjectName("shaderParamsDialog");
|
|
||||||
|
|
||||||
layout = new QVBoxLayout();
|
|
||||||
widget = new QWidget();
|
|
||||||
widget->setLayout(layout);
|
|
||||||
widget->setObjectName("shaderParamsWidget");
|
|
||||||
scrollArea = new QScrollArea(m_shaderParamsDialog);
|
|
||||||
scrollArea->setWidgetResizable(true);
|
|
||||||
scrollArea->setWidget(widget);
|
|
||||||
scrollArea->setObjectName("shaderParamsScrollArea");
|
|
||||||
|
|
||||||
m_shaderParamsDialog->setProperty("scrollArea", QVariant::fromValue(scrollArea));
|
|
||||||
|
|
||||||
connect(m_shaderParamsDialog, SIGNAL(closed()), m_shaderParamsDialog, SLOT(deleteLater()));
|
|
||||||
connect(m_shaderParamsDialog, SIGNAL(resized(QSize)), this, SLOT(onShaderParamsDialogResized(QSize)));
|
|
||||||
|
|
||||||
if (shader_info.data->num_parameters == 0)
|
|
||||||
{
|
|
||||||
QLabel *label = new QLabel(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SHADER_PARAMETERS), m_shaderParamsDialog);
|
|
||||||
label->setAlignment(Qt::AlignCenter);
|
|
||||||
|
|
||||||
layout->addWidget(label);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* NOTE: We assume that parameters are always grouped in order by the pass number, e.g., all parameters for pass 0 come first, then params for pass 1, etc. */
|
|
||||||
for (i = 0; i < shader_info.data->num_parameters; i++)
|
|
||||||
{
|
|
||||||
struct video_shader_parameter *param = &shader_info.data->parameters[i];
|
|
||||||
QString desc = param->desc;
|
|
||||||
QFormLayout *form = last_form;
|
|
||||||
|
|
||||||
if (param->pass > last_pass)
|
|
||||||
{
|
|
||||||
QGroupBox *groupBox = NULL;
|
|
||||||
QFileInfo fileInfo(shader_info.data->pass[param->pass].source.path);
|
|
||||||
QString shaderBasename = fileInfo.completeBaseName();
|
|
||||||
|
|
||||||
form = new QFormLayout();
|
|
||||||
groupBox = new QGroupBox(shaderBasename);
|
|
||||||
groupBox->setLayout(form);
|
|
||||||
|
|
||||||
layout->addWidget(groupBox);
|
|
||||||
|
|
||||||
last_form = form;
|
|
||||||
last_pass = param->pass;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((param->minimum == 0.0)
|
|
||||||
&& (param->maximum
|
|
||||||
== (param->minimum
|
|
||||||
+ param->step)))
|
|
||||||
{
|
|
||||||
/* option is basically a bool, so use a checkbox */
|
|
||||||
QCheckBox *checkBox = new QCheckBox(m_shaderParamsDialog);
|
|
||||||
checkBox->setChecked(param->current == param->maximum ? true : false);
|
|
||||||
checkBox->setProperty("param", QVariant::fromValue(param));
|
|
||||||
|
|
||||||
connect(checkBox, SIGNAL(clicked()), this, SLOT(onShaderParamCheckBoxClicked()));
|
|
||||||
|
|
||||||
form->addRow(desc, checkBox);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QDoubleSpinBox *doubleSpinBox = NULL;
|
|
||||||
QSpinBox *spinBox = NULL;
|
|
||||||
QHBoxLayout *box = new QHBoxLayout();
|
|
||||||
QSlider *slider = new QSlider(Qt::Horizontal, m_shaderParamsDialog);
|
|
||||||
double value = lerp(param->minimum, param->maximum, 0, 100, param->current);
|
|
||||||
double intpart = 0;
|
|
||||||
bool stepIsFractional = modf(param->step, &intpart);
|
|
||||||
|
|
||||||
slider->setRange(0, 100);
|
|
||||||
slider->setSingleStep(1);
|
|
||||||
slider->setValue(value);
|
|
||||||
slider->setProperty("param", QVariant::fromValue(param));
|
|
||||||
|
|
||||||
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(onShaderParamSliderValueChanged(int)));
|
|
||||||
|
|
||||||
box->addWidget(slider);
|
|
||||||
|
|
||||||
if (stepIsFractional)
|
|
||||||
{
|
|
||||||
doubleSpinBox = new QDoubleSpinBox(m_shaderParamsDialog);
|
|
||||||
doubleSpinBox->setRange(param->minimum, param->maximum);
|
|
||||||
doubleSpinBox->setSingleStep(param->step);
|
|
||||||
doubleSpinBox->setValue(param->current);
|
|
||||||
doubleSpinBox->setProperty("slider", QVariant::fromValue(slider));
|
|
||||||
slider->setProperty("doubleSpinBox", QVariant::fromValue(doubleSpinBox));
|
|
||||||
|
|
||||||
connect(doubleSpinBox, SIGNAL(valueChanged(double)), this, SLOT(onShaderParamDoubleSpinBoxValueChanged(double)));
|
|
||||||
|
|
||||||
box->addWidget(doubleSpinBox);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
spinBox = new QSpinBox(m_shaderParamsDialog);
|
|
||||||
spinBox->setRange(param->minimum, param->maximum);
|
|
||||||
spinBox->setSingleStep(param->step);
|
|
||||||
spinBox->setValue(param->current);
|
|
||||||
spinBox->setProperty("slider", QVariant::fromValue(slider));
|
|
||||||
slider->setProperty("spinBox", QVariant::fromValue(spinBox));
|
|
||||||
|
|
||||||
connect(spinBox, SIGNAL(valueChanged(int)), this, SLOT(onShaderParamSpinBoxValueChanged(int)));
|
|
||||||
|
|
||||||
box->addWidget(spinBox);
|
|
||||||
}
|
|
||||||
|
|
||||||
form->addRow(desc, box);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
layout->addItem(new QSpacerItem(20, 20, QSizePolicy::Minimum, QSizePolicy::Expanding));
|
|
||||||
}
|
|
||||||
|
|
||||||
m_shaderParamsDialog->resize(720, 480);
|
|
||||||
m_shaderParamsDialog->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onShaderParamCheckBoxClicked()
|
|
||||||
{
|
|
||||||
QCheckBox *checkBox = qobject_cast<QCheckBox*>(sender());
|
|
||||||
QVariant paramVariant;
|
|
||||||
struct video_shader_parameter *param = NULL;
|
|
||||||
|
|
||||||
if (!checkBox)
|
|
||||||
return;
|
|
||||||
|
|
||||||
paramVariant = checkBox->property("param");
|
|
||||||
|
|
||||||
if (paramVariant.isValid())
|
|
||||||
{
|
|
||||||
param = paramVariant.value<struct video_shader_parameter*>();
|
|
||||||
|
|
||||||
if (param)
|
|
||||||
param->current = (checkBox->isChecked() ? param->maximum : param->minimum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onShaderParamSliderValueChanged(int value)
|
|
||||||
{
|
|
||||||
QVariant spinBoxVariant;
|
|
||||||
QVariant paramVariant;
|
|
||||||
QSlider *slider = qobject_cast<QSlider*>(sender());
|
|
||||||
struct video_shader_parameter *param = NULL;
|
|
||||||
double newValue = 0.0;
|
|
||||||
|
|
||||||
if (!slider)
|
|
||||||
return;
|
|
||||||
|
|
||||||
spinBoxVariant = slider->property("spinBox");
|
|
||||||
paramVariant = slider->property("param");
|
|
||||||
|
|
||||||
if (paramVariant.isValid())
|
|
||||||
{
|
|
||||||
param = paramVariant.value<struct video_shader_parameter*>();
|
|
||||||
|
|
||||||
if (param)
|
|
||||||
{
|
|
||||||
newValue = lerp(0, 100, param->minimum, param->maximum, slider->value());
|
|
||||||
param->current = newValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spinBoxVariant.isValid())
|
|
||||||
{
|
|
||||||
QSpinBox *spinBox = spinBoxVariant.value<QSpinBox*>();
|
|
||||||
|
|
||||||
if (!spinBox)
|
|
||||||
return;
|
|
||||||
|
|
||||||
spinBox->blockSignals(true);
|
|
||||||
spinBox->setValue(newValue);
|
|
||||||
spinBox->blockSignals(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
QVariant doubleSpinBoxVariant = slider->property("doubleSpinBox");
|
|
||||||
QDoubleSpinBox *doubleSpinBox = doubleSpinBoxVariant.value<QDoubleSpinBox*>();
|
|
||||||
|
|
||||||
if (!doubleSpinBox)
|
|
||||||
return;
|
|
||||||
|
|
||||||
doubleSpinBox->blockSignals(true);
|
|
||||||
doubleSpinBox->setValue(newValue);
|
|
||||||
doubleSpinBox->blockSignals(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onShaderParamSpinBoxValueChanged(int value)
|
|
||||||
{
|
|
||||||
QSpinBox *spinBox = qobject_cast<QSpinBox*>(sender());
|
|
||||||
QVariant sliderVariant;
|
|
||||||
QVariant paramVariant;
|
|
||||||
QSlider *slider = NULL;
|
|
||||||
struct video_shader_parameter *param = NULL;
|
|
||||||
double newValue = 0.0;
|
|
||||||
|
|
||||||
if (!spinBox)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sliderVariant = spinBox->property("slider");
|
|
||||||
|
|
||||||
if (!sliderVariant.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
slider = sliderVariant.value<QSlider*>();
|
|
||||||
|
|
||||||
if (!slider)
|
|
||||||
return;
|
|
||||||
|
|
||||||
paramVariant = slider->property("param");
|
|
||||||
|
|
||||||
if (paramVariant.isValid())
|
|
||||||
{
|
|
||||||
param = paramVariant.value<struct video_shader_parameter*>();
|
|
||||||
|
|
||||||
if (param)
|
|
||||||
{
|
|
||||||
param->current = value;
|
|
||||||
newValue = lerp(param->minimum, param->maximum, 0, 100, param->current);
|
|
||||||
slider->blockSignals(true);
|
|
||||||
slider->setValue(newValue);
|
|
||||||
slider->blockSignals(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onShaderParamDoubleSpinBoxValueChanged(double value)
|
|
||||||
{
|
|
||||||
QDoubleSpinBox *doubleSpinBox = qobject_cast<QDoubleSpinBox*>(sender());
|
|
||||||
QVariant sliderVariant;
|
|
||||||
QVariant paramVariant;
|
|
||||||
QSlider *slider = NULL;
|
|
||||||
struct video_shader_parameter *param = NULL;
|
|
||||||
double newValue = 0.0;
|
|
||||||
|
|
||||||
if (!doubleSpinBox)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sliderVariant = doubleSpinBox->property("slider");
|
|
||||||
|
|
||||||
if (!sliderVariant.isValid())
|
|
||||||
return;
|
|
||||||
|
|
||||||
slider = sliderVariant.value<QSlider*>();
|
|
||||||
|
|
||||||
if (!slider)
|
|
||||||
return;
|
|
||||||
|
|
||||||
paramVariant = slider->property("param");
|
|
||||||
|
|
||||||
if (paramVariant.isValid())
|
|
||||||
{
|
|
||||||
param = paramVariant.value<struct video_shader_parameter*>();
|
|
||||||
|
|
||||||
if (param)
|
|
||||||
{
|
|
||||||
param->current = value;
|
|
||||||
newValue = lerp(param->minimum, param->maximum, 0, 100, param->current);
|
|
||||||
slider->blockSignals(true);
|
|
||||||
slider->setValue(newValue);
|
|
||||||
slider->blockSignals(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onGridItemClicked(ThumbnailWidget *widget)
|
void MainWindow::onGridItemClicked(ThumbnailWidget *widget)
|
||||||
{
|
{
|
||||||
QHash<QString, QString> hash;
|
QHash<QString, QString> hash;
|
||||||
|
@ -1140,105 +834,6 @@ bool MainWindow::showMessageBox(QString msg, MessageBoxType msgType, Qt::WindowM
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onFileDropWidgetContextMenuRequested(const QPoint &pos)
|
|
||||||
{
|
|
||||||
QScopedPointer<QMenu> menu;
|
|
||||||
QScopedPointer<QAction> addEntryAction;
|
|
||||||
QScopedPointer<QAction> addFilesAction;
|
|
||||||
QScopedPointer<QAction> addFolderAction;
|
|
||||||
QScopedPointer<QAction> editAction;
|
|
||||||
QScopedPointer<QAction> deleteAction;
|
|
||||||
QPointer<QAction> selectedAction;
|
|
||||||
QPoint cursorPos = QCursor::pos();
|
|
||||||
QHash<QString, QString> contentHash = getCurrentContentHash();
|
|
||||||
|
|
||||||
menu.reset(new QMenu(this));
|
|
||||||
|
|
||||||
addEntryAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ADD_ENTRY)), this));
|
|
||||||
addFilesAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ADD_FILES)), this));
|
|
||||||
addFolderAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_ADD_FOLDER)), this));
|
|
||||||
editAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_EDIT)), this));
|
|
||||||
deleteAction.reset(new QAction(QString(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_DELETE)), this));
|
|
||||||
|
|
||||||
menu->addAction(addEntryAction.data());
|
|
||||||
menu->addAction(addFilesAction.data());
|
|
||||||
menu->addAction(addFolderAction.data());
|
|
||||||
|
|
||||||
if (!contentHash.isEmpty())
|
|
||||||
{
|
|
||||||
menu->addAction(editAction.data());
|
|
||||||
menu->addAction(deleteAction.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedAction = menu->exec(cursorPos);
|
|
||||||
|
|
||||||
if (!selectedAction)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (selectedAction == addFilesAction.data())
|
|
||||||
{
|
|
||||||
QStringList filePaths = QFileDialog::getOpenFileNames(this, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_SELECT_FILES));
|
|
||||||
|
|
||||||
if (!filePaths.isEmpty())
|
|
||||||
addFilesToPlaylist(filePaths);
|
|
||||||
}
|
|
||||||
else if (selectedAction == addEntryAction.data())
|
|
||||||
{
|
|
||||||
addFilesToPlaylist(QStringList());
|
|
||||||
}
|
|
||||||
else if (selectedAction == addFolderAction.data())
|
|
||||||
{
|
|
||||||
QString dirPath = QFileDialog::getExistingDirectory(this, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_SELECT_FOLDER), QString(), QFileDialog::ShowDirsOnly);
|
|
||||||
|
|
||||||
if (!dirPath.isEmpty())
|
|
||||||
addFilesToPlaylist(QStringList() << dirPath);
|
|
||||||
}
|
|
||||||
else if (selectedAction == editAction.data())
|
|
||||||
{
|
|
||||||
PlaylistEntryDialog *playlistDialog = playlistEntryDialog();
|
|
||||||
QHash<QString, QString> selectedCore;
|
|
||||||
QString selectedDatabase;
|
|
||||||
QString selectedName;
|
|
||||||
QString selectedPath;
|
|
||||||
QString currentPlaylistPath = getCurrentPlaylistPath();
|
|
||||||
|
|
||||||
if (!playlistDialog->showDialog(contentHash))
|
|
||||||
return;
|
|
||||||
|
|
||||||
selectedName = m_playlistEntryDialog->getSelectedName();
|
|
||||||
selectedPath = m_playlistEntryDialog->getSelectedPath();
|
|
||||||
selectedCore = m_playlistEntryDialog->getSelectedCore();
|
|
||||||
selectedDatabase = m_playlistEntryDialog->getSelectedDatabase();
|
|
||||||
|
|
||||||
if (selectedCore.isEmpty())
|
|
||||||
{
|
|
||||||
selectedCore["core_name"] = "DETECT";
|
|
||||||
selectedCore["core_path"] = "DETECT";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedDatabase.isEmpty())
|
|
||||||
{
|
|
||||||
selectedDatabase = QFileInfo(currentPlaylistPath).fileName().remove(file_path_str(FILE_PATH_LPL_EXTENSION));
|
|
||||||
}
|
|
||||||
|
|
||||||
contentHash["label"] = selectedName;
|
|
||||||
contentHash["path"] = selectedPath;
|
|
||||||
contentHash["core_name"] = selectedCore.value("core_name");
|
|
||||||
contentHash["core_path"] = selectedCore.value("core_path");
|
|
||||||
contentHash["db_name"] = selectedDatabase;
|
|
||||||
|
|
||||||
if (!updateCurrentPlaylistEntry(contentHash))
|
|
||||||
{
|
|
||||||
showMessageBox(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_UPDATE_PLAYLIST_ENTRY), MainWindow::MSGBOX_TYPE_ERROR, Qt::ApplicationModal, false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (selectedAction == deleteAction.data())
|
|
||||||
{
|
|
||||||
deleteCurrentPlaylistItem();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::onFileBrowserTreeContextMenuRequested(const QPoint&)
|
void MainWindow::onFileBrowserTreeContextMenuRequested(const QPoint&)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_LIBRETRODB
|
#ifdef HAVE_LIBRETRODB
|
||||||
|
@ -1324,10 +919,20 @@ void MainWindow::deferReloadShaderParams()
|
||||||
emit gotReloadShaderParams();
|
emit gotReloadShaderParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onShaderParamsClicked()
|
||||||
|
{
|
||||||
|
if (!m_shaderParamsDialog)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_shaderParamsDialog->show();
|
||||||
|
|
||||||
|
onGotReloadShaderParams();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::onGotReloadShaderParams()
|
void MainWindow::onGotReloadShaderParams()
|
||||||
{
|
{
|
||||||
if (m_shaderParamsDialog && m_shaderParamsDialog->isVisible())
|
if (m_shaderParamsDialog && m_shaderParamsDialog->isVisible())
|
||||||
onShaderParamsClicked();
|
m_shaderParamsDialog->reload();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::appendLogMessage(const QString &msg)
|
void MainWindow::appendLogMessage(const QString &msg)
|
||||||
|
@ -1835,7 +1440,6 @@ void MainWindow::onTableWidgetDeletePressed()
|
||||||
QHash<QString, QString> MainWindow::getCurrentContentHash()
|
QHash<QString, QString> MainWindow::getCurrentContentHash()
|
||||||
{
|
{
|
||||||
QTableWidgetItem *contentItem = m_tableWidget->currentItem();
|
QTableWidgetItem *contentItem = m_tableWidget->currentItem();
|
||||||
QListWidgetItem *playlistItem = m_listWidget->currentItem();
|
|
||||||
QHash<QString, QString> contentHash;
|
QHash<QString, QString> contentHash;
|
||||||
ViewType viewType = getCurrentViewType();
|
ViewType viewType = getCurrentViewType();
|
||||||
|
|
||||||
|
|
|
@ -324,7 +324,7 @@ static void* ui_companion_qt_init(void)
|
||||||
|
|
||||||
QObject::connect(viewClosedDocksMenu, SIGNAL(aboutToShow()), mainwindow, SLOT(onViewClosedDocksAboutToShow()));
|
QObject::connect(viewClosedDocksMenu, SIGNAL(aboutToShow()), mainwindow, SLOT(onViewClosedDocksAboutToShow()));
|
||||||
|
|
||||||
viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_SHADER_PARAMS), mainwindow, SLOT(onShaderParamsClicked()));
|
viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SHADER_OPTIONS), mainwindow, SLOT(onShaderParamsClicked()));
|
||||||
|
|
||||||
viewMenu->addSeparator();
|
viewMenu->addSeparator();
|
||||||
viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_VIEW_TYPE_ICONS), mainwindow, SLOT(onIconViewClicked()));
|
viewMenu->addAction(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_QT_VIEW_TYPE_ICONS), mainwindow, SLOT(onIconViewClicked()));
|
||||||
|
@ -634,26 +634,6 @@ static void ui_companion_qt_event_command(void *data, enum event_command cmd)
|
||||||
switch (cmd)
|
switch (cmd)
|
||||||
{
|
{
|
||||||
case CMD_EVENT_SHADERS_APPLY_CHANGES:
|
case CMD_EVENT_SHADERS_APPLY_CHANGES:
|
||||||
{
|
|
||||||
/* If shader was turned off, reload the params window manually because PRESET_LOADED won't be fired */
|
|
||||||
video_shader_ctx_t shader_info = {0};
|
|
||||||
|
|
||||||
if (!video_shader_driver_get_current_shader(&shader_info))
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Isn't there a better way to do this? */
|
|
||||||
if (shader_info.data && shader_info.data->num_parameters == 0)
|
|
||||||
{
|
|
||||||
if (shader_info.data->passes == 1 && string_is_empty(shader_info.data->pass[0].source.path))
|
|
||||||
{
|
|
||||||
RARCH_LOG("[Qt]: Clearing shader parameters.\n");
|
|
||||||
win_handle->qtWindow->deferReloadShaderParams();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Otherwise, PRESET_LOADED fires in more situations than APPLY_CHANGES, so use that for reloading the params window */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CMD_EVENT_SHADER_PRESET_LOADED:
|
case CMD_EVENT_SHADER_PRESET_LOADED:
|
||||||
RARCH_LOG("[Qt]: Reloading shader parameters.\n");
|
RARCH_LOG("[Qt]: Reloading shader parameters.\n");
|
||||||
win_handle->qtWindow->deferReloadShaderParams();
|
win_handle->qtWindow->deferReloadShaderParams();
|
||||||
|
|
|
@ -368,11 +368,6 @@ private slots:
|
||||||
void onShowErrorMessage(QString msg);
|
void onShowErrorMessage(QString msg);
|
||||||
void onShowInfoMessage(QString msg);
|
void onShowInfoMessage(QString msg);
|
||||||
void onContributorsClicked();
|
void onContributorsClicked();
|
||||||
void onShaderParamCheckBoxClicked();
|
|
||||||
void onShaderParamSliderValueChanged(int value);
|
|
||||||
void onShaderParamSpinBoxValueChanged(int value);
|
|
||||||
void onShaderParamDoubleSpinBoxValueChanged(double value);
|
|
||||||
void onShaderParamsDialogResized(QSize size);
|
|
||||||
int onExtractArchive(QString path);
|
int onExtractArchive(QString path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -57,6 +57,7 @@ typedef struct ui_companion_win32
|
||||||
void *empty;
|
void *empty;
|
||||||
} ui_companion_win32_t;
|
} ui_companion_win32_t;
|
||||||
|
|
||||||
|
#ifndef __WINRT__
|
||||||
bool win32_window_init(WNDCLASSEX *wndclass,
|
bool win32_window_init(WNDCLASSEX *wndclass,
|
||||||
bool fullscreen, const char *class_name)
|
bool fullscreen, const char *class_name)
|
||||||
{
|
{
|
||||||
|
@ -79,7 +80,7 @@ bool win32_window_init(WNDCLASSEX *wndclass,
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool win32_browser(
|
static bool win32_browser(
|
||||||
HWND owner,
|
HWND owner,
|
||||||
|
|
Loading…
Reference in New Issue