mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-28 10:40:39 +00:00
AI Service overlay.
This commit is contained in:
parent
14f8ee1e40
commit
d641e67876
@ -2284,10 +2284,24 @@ void menu_display_draw(menu_display_ctx_draw_t *draw,
|
|||||||
return;
|
return;
|
||||||
if (draw->width <= 0)
|
if (draw->width <= 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
menu_disp->draw(draw, video_info);
|
menu_disp->draw(draw, video_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void menu_display_draw_blend(menu_display_ctx_draw_t *draw,
|
||||||
|
video_frame_info_t *video_info)
|
||||||
|
{
|
||||||
|
if (!menu_disp || !draw || !menu_disp->draw)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (draw->height <= 0)
|
||||||
|
return;
|
||||||
|
if (draw->width <= 0)
|
||||||
|
return;
|
||||||
|
menu_display_blend_begin(video_info);
|
||||||
|
menu_disp->draw(draw, video_info);
|
||||||
|
menu_display_blend_end(video_info);
|
||||||
|
}
|
||||||
|
|
||||||
void menu_display_draw_pipeline(menu_display_ctx_draw_t *draw,
|
void menu_display_draw_pipeline(menu_display_ctx_draw_t *draw,
|
||||||
video_frame_info_t *video_info)
|
video_frame_info_t *video_info)
|
||||||
{
|
{
|
||||||
@ -3185,6 +3199,35 @@ bool menu_display_reset_textures_list(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool menu_display_reset_textures_list_buffer(
|
||||||
|
uintptr_t *item, enum texture_filter_type filter_type,
|
||||||
|
void* buffer, unsigned buffer_len, enum image_type_enum image_type,
|
||||||
|
unsigned *width, unsigned *height)
|
||||||
|
{
|
||||||
|
struct texture_image ti;
|
||||||
|
|
||||||
|
ti.width = 0;
|
||||||
|
ti.height = 0;
|
||||||
|
ti.pixels = NULL;
|
||||||
|
ti.supports_rgba = video_driver_supports_rgba();
|
||||||
|
|
||||||
|
if (!image_texture_load_buffer(&ti, image_type, buffer, buffer_len))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
*width = ti.width;
|
||||||
|
|
||||||
|
if (height)
|
||||||
|
*height = ti.height;
|
||||||
|
|
||||||
|
/* if the poke interface doesn't support texture load then return false */
|
||||||
|
if (!video_driver_texture_load(&ti, filter_type, item))
|
||||||
|
return false;
|
||||||
|
image_texture_free(&ti);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* menu_driver_find_handle:
|
* menu_driver_find_handle:
|
||||||
* @idx : index of driver to get handle to.
|
* @idx : index of driver to get handle to.
|
||||||
|
@ -583,6 +583,8 @@ void menu_display_clear_color(menu_display_ctx_clearcolor_t *color,
|
|||||||
video_frame_info_t *video_info);
|
video_frame_info_t *video_info);
|
||||||
void menu_display_draw(menu_display_ctx_draw_t *draw,
|
void menu_display_draw(menu_display_ctx_draw_t *draw,
|
||||||
video_frame_info_t *video_info);
|
video_frame_info_t *video_info);
|
||||||
|
void menu_display_draw_blend(menu_display_ctx_draw_t *draw,
|
||||||
|
video_frame_info_t *video_info);
|
||||||
void menu_display_draw_keyboard(
|
void menu_display_draw_keyboard(
|
||||||
uintptr_t hover_texture,
|
uintptr_t hover_texture,
|
||||||
const font_data_t *font,
|
const font_data_t *font,
|
||||||
@ -680,6 +682,11 @@ bool menu_display_reset_textures_list(
|
|||||||
uintptr_t *item, enum texture_filter_type filter_type,
|
uintptr_t *item, enum texture_filter_type filter_type,
|
||||||
unsigned *width, unsigned *height);
|
unsigned *width, unsigned *height);
|
||||||
|
|
||||||
|
bool menu_display_reset_textures_list_buffer(
|
||||||
|
uintptr_t *item, enum texture_filter_type filter_type,
|
||||||
|
void* buffer, unsigned buffer_len, enum image_type_enum image_type,
|
||||||
|
unsigned *width, unsigned *height);
|
||||||
|
|
||||||
/* Returns the OSK key at a given position */
|
/* Returns the OSK key at a given position */
|
||||||
int menu_display_osk_ptr_at_pos(void *data, int x, int y,
|
int menu_display_osk_ptr_at_pos(void *data, int x, int y,
|
||||||
unsigned width, unsigned height);
|
unsigned width, unsigned height);
|
||||||
|
@ -261,6 +261,12 @@ static menu_timer_t screenshot_timer;
|
|||||||
|
|
||||||
static unsigned screenshot_shotname_length;
|
static unsigned screenshot_shotname_length;
|
||||||
|
|
||||||
|
/* AI Service Overlay */
|
||||||
|
static int ai_service_overlay_state = 0;
|
||||||
|
static unsigned ai_service_overlay_width = 0;
|
||||||
|
static unsigned ai_service_overlay_height = 0;
|
||||||
|
static menu_texture_item ai_service_overlay_texture = 0;
|
||||||
|
|
||||||
/* Generic message */
|
/* Generic message */
|
||||||
static menu_timer_t generic_message_timer;
|
static menu_timer_t generic_message_timer;
|
||||||
static float generic_message_alpha = 0.0f;
|
static float generic_message_alpha = 0.0f;
|
||||||
@ -709,6 +715,55 @@ static void menu_widgets_draw_icon(
|
|||||||
menu_display_draw(&draw, video_info);
|
menu_display_draw(&draw, video_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void menu_widgets_draw_icon_blend(
|
||||||
|
video_frame_info_t *video_info,
|
||||||
|
unsigned icon_width,
|
||||||
|
unsigned icon_height,
|
||||||
|
uintptr_t texture,
|
||||||
|
float x, float y,
|
||||||
|
unsigned width, unsigned height,
|
||||||
|
float rotation, float scale_factor,
|
||||||
|
float *color)
|
||||||
|
{
|
||||||
|
menu_display_ctx_rotate_draw_t rotate_draw;
|
||||||
|
menu_display_ctx_draw_t draw;
|
||||||
|
struct video_coords coords;
|
||||||
|
math_matrix_4x4 mymat;
|
||||||
|
|
||||||
|
if (!texture)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rotate_draw.matrix = &mymat;
|
||||||
|
rotate_draw.rotation = rotation;
|
||||||
|
rotate_draw.scale_x = scale_factor;
|
||||||
|
rotate_draw.scale_y = scale_factor;
|
||||||
|
rotate_draw.scale_z = 1;
|
||||||
|
rotate_draw.scale_enable = true;
|
||||||
|
|
||||||
|
menu_display_rotate_z(&rotate_draw, video_info);
|
||||||
|
|
||||||
|
coords.vertices = 4;
|
||||||
|
coords.vertex = NULL;
|
||||||
|
coords.tex_coord = NULL;
|
||||||
|
coords.lut_tex_coord = NULL;
|
||||||
|
coords.color = color;
|
||||||
|
|
||||||
|
draw.x = x;
|
||||||
|
draw.y = height - y - icon_height;
|
||||||
|
draw.width = icon_width;
|
||||||
|
draw.height = icon_height;
|
||||||
|
draw.scale_factor = scale_factor;
|
||||||
|
draw.rotation = rotation;
|
||||||
|
draw.coords = &coords;
|
||||||
|
draw.matrix_data = &mymat;
|
||||||
|
draw.texture = texture;
|
||||||
|
draw.prim_type = MENU_DISPLAY_PRIM_TRIANGLESTRIP;
|
||||||
|
draw.pipeline.id = 0;
|
||||||
|
|
||||||
|
menu_display_draw_blend(&draw, video_info);
|
||||||
|
}
|
||||||
|
|
||||||
static float menu_widgets_get_thumbnail_scale_factor(const float dst_width, const float dst_height,
|
static float menu_widgets_get_thumbnail_scale_factor(const float dst_width, const float dst_height,
|
||||||
const float image_width, const float image_height)
|
const float image_width, const float image_height)
|
||||||
{
|
{
|
||||||
@ -1134,7 +1189,6 @@ static void menu_widgets_draw_regular_msg(menu_widget_msg_t *msg, video_frame_in
|
|||||||
(msg_queue_scissor_start_x + msg->width - simple_widget_padding*2) * msg->unfold, video_info->height);
|
(msg_queue_scissor_start_x + msg->width - simple_widget_padding*2) * msg->unfold, video_info->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (msg_queue_has_icons)
|
if (msg_queue_has_icons)
|
||||||
{
|
{
|
||||||
menu_display_blend_begin(video_info);
|
menu_display_blend_begin(video_info);
|
||||||
@ -1286,6 +1340,57 @@ void menu_widgets_frame(video_frame_info_t *video_info)
|
|||||||
font_raster_regular.carr.coords.vertices = 0;
|
font_raster_regular.carr.coords.vertices = 0;
|
||||||
font_raster_bold.carr.coords.vertices = 0;
|
font_raster_bold.carr.coords.vertices = 0;
|
||||||
|
|
||||||
|
/* AI Service overlay */
|
||||||
|
if (ai_service_overlay_state > 0)
|
||||||
|
{
|
||||||
|
float outline_color[16] = {
|
||||||
|
0.00, 1.00, 0.00, 1.00,
|
||||||
|
0.00, 1.00, 0.00, 1.00,
|
||||||
|
0.00, 1.00, 0.00, 1.00,
|
||||||
|
0.00, 1.00, 0.00, 1.00,
|
||||||
|
};
|
||||||
|
|
||||||
|
menu_widgets_draw_icon_blend(video_info,
|
||||||
|
video_info->width, video_info->height,
|
||||||
|
ai_service_overlay_texture,
|
||||||
|
0, 0,
|
||||||
|
video_info->width, video_info->height,
|
||||||
|
0, 1, menu_widgets_pure_white
|
||||||
|
);
|
||||||
|
/* top line */
|
||||||
|
menu_display_draw_quad(video_info,
|
||||||
|
0, 0,
|
||||||
|
video_info->width, 1,
|
||||||
|
video_info->width, video_info->height,
|
||||||
|
outline_color
|
||||||
|
);
|
||||||
|
/* bottom line */
|
||||||
|
menu_display_draw_quad(video_info,
|
||||||
|
0, video_info->height-1,
|
||||||
|
video_info->width, 1,
|
||||||
|
video_info->width, video_info->height,
|
||||||
|
outline_color
|
||||||
|
);
|
||||||
|
/* left line */
|
||||||
|
menu_display_draw_quad(video_info,
|
||||||
|
0, 0,
|
||||||
|
1, video_info->height,
|
||||||
|
video_info->width, video_info->height,
|
||||||
|
outline_color
|
||||||
|
);
|
||||||
|
/* right line */
|
||||||
|
menu_display_draw_quad(video_info,
|
||||||
|
video_info->width-1, 0,
|
||||||
|
1, video_info->height,
|
||||||
|
video_info->width, video_info->height,
|
||||||
|
outline_color
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ai_service_overlay_state == 2)
|
||||||
|
ai_service_overlay_state = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Libretro message */
|
/* Libretro message */
|
||||||
if (libretro_message_alpha > 0.0f)
|
if (libretro_message_alpha > 0.0f)
|
||||||
{
|
{
|
||||||
@ -1957,6 +2062,9 @@ void menu_widgets_free(void)
|
|||||||
menu_timer_kill(&libretro_message_timer);
|
menu_timer_kill(&libretro_message_timer);
|
||||||
menu_animation_kill_by_tag(&libretro_tag);
|
menu_animation_kill_by_tag(&libretro_tag);
|
||||||
|
|
||||||
|
/* AI Service overlay */
|
||||||
|
/* ... */
|
||||||
|
|
||||||
/* Volume */
|
/* Volume */
|
||||||
volume_alpha = 0.0f;
|
volume_alpha = 0.0f;
|
||||||
|
|
||||||
@ -2014,6 +2122,46 @@ bool menu_widgets_set_fps_text(const char *new_fps_text)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int menu_widgets_ai_service_overlay_get_state()
|
||||||
|
{
|
||||||
|
return ai_service_overlay_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool menu_widgets_ai_service_overlay_set_state(int state)
|
||||||
|
{
|
||||||
|
ai_service_overlay_state = state;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool menu_widgets_ai_service_overlay_load(
|
||||||
|
char* buffer, unsigned buffer_len, enum image_type_enum image_type)
|
||||||
|
{
|
||||||
|
if (ai_service_overlay_state == 0)
|
||||||
|
{
|
||||||
|
bool res;
|
||||||
|
res = menu_display_reset_textures_list_buffer(
|
||||||
|
&ai_service_overlay_texture,
|
||||||
|
TEXTURE_FILTER_MIPMAP_LINEAR,
|
||||||
|
(void *) buffer, buffer_len, image_type,
|
||||||
|
&ai_service_overlay_width, &ai_service_overlay_height);
|
||||||
|
if (res)
|
||||||
|
ai_service_overlay_state = 1;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void menu_widgets_ai_service_overlay_unload()
|
||||||
|
{
|
||||||
|
if (ai_service_overlay_state == 1)
|
||||||
|
{
|
||||||
|
video_driver_texture_unload(&ai_service_overlay_texture);
|
||||||
|
ai_service_overlay_state = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void menu_widgets_screenshot_fadeout(void *userdata)
|
static void menu_widgets_screenshot_fadeout(void *userdata)
|
||||||
{
|
{
|
||||||
menu_animation_ctx_entry_t entry;
|
menu_animation_ctx_entry_t entry;
|
||||||
|
@ -55,6 +55,15 @@ void menu_widgets_iterate(unsigned width, unsigned height);
|
|||||||
|
|
||||||
void menu_widgets_screenshot_taken(const char *shotname, const char *filename);
|
void menu_widgets_screenshot_taken(const char *shotname, const char *filename);
|
||||||
|
|
||||||
|
/* AI Service functions */
|
||||||
|
int menu_widgets_ai_service_overlay_get_state();
|
||||||
|
bool menu_widgets_ai_service_overlay_set_state(int state);
|
||||||
|
|
||||||
|
bool menu_widgets_ai_service_overlay_load(
|
||||||
|
char* buffer, unsigned buffer_len, enum image_type_enum image_type);
|
||||||
|
void menu_widgets_ai_service_overlay_unload();
|
||||||
|
|
||||||
|
|
||||||
void menu_widgets_start_load_content_animation(const char *content_name, bool remove_extension);
|
void menu_widgets_start_load_content_animation(const char *content_name, bool remove_extension);
|
||||||
|
|
||||||
void menu_widgets_cleanup_load_content_animation(void);
|
void menu_widgets_cleanup_load_content_animation(void);
|
||||||
|
211
retroarch.c
211
retroarch.c
@ -2730,11 +2730,10 @@ static void handle_translation_cb(
|
|||||||
int i = 0;
|
int i = 0;
|
||||||
int start = -1;
|
int start = -1;
|
||||||
char* found_string = NULL;
|
char* found_string = NULL;
|
||||||
|
char* error_string = NULL;
|
||||||
int curr_state = 0;
|
int curr_state = 0;
|
||||||
|
|
||||||
if (!is_paused && settings->uints.ai_service_mode != 1)
|
RARCH_LOG("RESULT FROM AI SERVICE...\n");
|
||||||
goto finish;
|
|
||||||
|
|
||||||
if (!data || error)
|
if (!data || error)
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
@ -2775,6 +2774,12 @@ static void handle_translation_cb(
|
|||||||
curr_state = 0;
|
curr_state = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
else if (curr_state == 3)
|
||||||
|
{
|
||||||
|
error_string = (char*)malloc(i-start+1);
|
||||||
|
strlcpy(error_string, body_copy+start+1, i-start);
|
||||||
|
curr_state = 0;
|
||||||
|
}
|
||||||
else if (string_is_equal(found_string, "image"))
|
else if (string_is_equal(found_string, "image"))
|
||||||
{
|
{
|
||||||
curr_state = 1;
|
curr_state = 1;
|
||||||
@ -2785,15 +2790,34 @@ static void handle_translation_cb(
|
|||||||
curr_state = 2;
|
curr_state = 2;
|
||||||
free(found_string);
|
free(found_string);
|
||||||
}
|
}
|
||||||
|
else if (string_is_equal(found_string, "error"))
|
||||||
|
{
|
||||||
|
curr_state = 3;
|
||||||
|
free(found_string);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
curr_state = 0;
|
curr_state = 0;
|
||||||
|
free(found_string);
|
||||||
|
}
|
||||||
start = -1;
|
start = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
if (found_string)
|
|
||||||
free(found_string);
|
if (string_is_equal(error_string, "No text found."))
|
||||||
|
{
|
||||||
|
RARCH_LOG("No text found...\n");
|
||||||
|
#ifdef HAVE_MENU_WIDGETS
|
||||||
|
if (menu_widgets_paused)
|
||||||
|
{
|
||||||
|
/* In this case we have to unpause and then repause for a frame */
|
||||||
|
menu_widgets_ai_service_overlay_set_state(2);
|
||||||
|
command_event(CMD_EVENT_UNPAUSE, NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
if (!raw_image_file_data && !raw_sound_data)
|
if (!raw_image_file_data && !raw_sound_data)
|
||||||
{
|
{
|
||||||
@ -2806,6 +2830,60 @@ static void handle_translation_cb(
|
|||||||
/* Get the video frame dimensions reference */
|
/* Get the video frame dimensions reference */
|
||||||
video_driver_cached_frame_get(&dummy_data, &width, &height, &pitch);
|
video_driver_cached_frame_get(&dummy_data, &width, &height, &pitch);
|
||||||
|
|
||||||
|
/* try two different modes for text display *
|
||||||
|
* In the first mode, we use menu widget overlays, but they require
|
||||||
|
* the video poke interface to be able to load image buffers.
|
||||||
|
*
|
||||||
|
* The other method is to draw to the video buffer directly, which needs
|
||||||
|
* a software core to be running. */
|
||||||
|
#ifdef HAVE_MENU_WIDGETS
|
||||||
|
if (video_driver_poke
|
||||||
|
&& video_driver_poke->load_texture && video_driver_poke->unload_texture)
|
||||||
|
{
|
||||||
|
bool ai_res;
|
||||||
|
enum image_type_enum image_type;
|
||||||
|
/* Write to overlay */
|
||||||
|
if (raw_image_file_data[0] == 'B' && raw_image_file_data[1] == 'M')
|
||||||
|
{
|
||||||
|
image_type = IMAGE_TYPE_BMP;
|
||||||
|
}
|
||||||
|
else if (raw_image_file_data[1] == 'P' &&
|
||||||
|
raw_image_file_data[2] == 'N' &&
|
||||||
|
raw_image_file_data[3] == 'G')
|
||||||
|
{
|
||||||
|
image_type = IMAGE_TYPE_PNG;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RARCH_LOG("Invalid image type returned from server.\n");
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
|
ai_res = menu_widgets_ai_service_overlay_load(
|
||||||
|
raw_image_file_data, (unsigned) new_image_size,
|
||||||
|
image_type);
|
||||||
|
|
||||||
|
if (!ai_res)
|
||||||
|
{
|
||||||
|
RARCH_LOG("Video driver not supported for AI Service.");
|
||||||
|
runloop_msg_queue_push(
|
||||||
|
/* msg_hash_to_str(MSG_VIDEO_DRIVER_NOT_SUPPORTED), */
|
||||||
|
"Video driver not supported.",
|
||||||
|
1, 180, true,
|
||||||
|
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
|
||||||
|
}
|
||||||
|
else if (menu_widgets_paused)
|
||||||
|
{
|
||||||
|
/* In this case we have to unpause and then repause for a frame */
|
||||||
|
menu_widgets_ai_service_overlay_set_state(2);/* Unpausing state */
|
||||||
|
command_event(CMD_EVENT_UNPAUSE, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
/* Can't use menu widget overlays, so try writing to video buffer */
|
||||||
|
{
|
||||||
|
/* Write to video buffer directly (software cores only) */
|
||||||
if (raw_image_file_data[0] == 'B' && raw_image_file_data[1] == 'M')
|
if (raw_image_file_data[0] == 'B' && raw_image_file_data[1] == 'M')
|
||||||
{
|
{
|
||||||
/* This is a BMP file coming back. */
|
/* This is a BMP file coming back. */
|
||||||
@ -2884,6 +2962,7 @@ static void handle_translation_cb(
|
|||||||
RARCH_LOG("Output from URL not a valid file type, or is not supported.\n");
|
RARCH_LOG("Output from URL not a valid file type, or is not supported.\n");
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
scaler = (struct scaler_ctx*)calloc(1, sizeof(struct scaler_ctx));
|
scaler = (struct scaler_ctx*)calloc(1, sizeof(struct scaler_ctx));
|
||||||
if (!scaler)
|
if (!scaler)
|
||||||
goto finish;
|
goto finish;
|
||||||
@ -2895,10 +2974,7 @@ static void handle_translation_cb(
|
|||||||
and translate it, and we have the translated image in
|
and translate it, and we have the translated image in
|
||||||
the raw_image_data buffer.
|
the raw_image_data buffer.
|
||||||
*/
|
*/
|
||||||
|
RARCH_LOG("Hardware frame buffer core, but selected video driver isn't supported.\n");
|
||||||
/* TODO: write to the viewport in this case */
|
|
||||||
RARCH_LOG("Hardware frame buffer... writing to viewport"
|
|
||||||
" not yet supported.\n");
|
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2939,6 +3015,7 @@ static void handle_translation_cb(
|
|||||||
(uint8_t*)raw_image_data + (image_height - 1) * width * 3);
|
(uint8_t*)raw_image_data + (image_height - 1) * width * 3);
|
||||||
video_driver_frame(raw_output_data, image_width, image_height, pitch);
|
video_driver_frame(raw_output_data, image_width, image_height, pitch);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef HAVE_AUDIOMIXER
|
#ifdef HAVE_AUDIOMIXER
|
||||||
if (raw_sound_data)
|
if (raw_sound_data)
|
||||||
@ -2998,7 +3075,8 @@ finish:
|
|||||||
free(raw_image_data);
|
free(raw_image_data);
|
||||||
if (scaler)
|
if (scaler)
|
||||||
free(scaler);
|
free(scaler);
|
||||||
|
if (error_string)
|
||||||
|
free(error_string);
|
||||||
if (raw_output_data)
|
if (raw_output_data)
|
||||||
free(raw_output_data);
|
free(raw_output_data);
|
||||||
}
|
}
|
||||||
@ -3163,10 +3241,10 @@ static const char *ai_service_get_str(enum translation_lang id)
|
|||||||
|
|
||||||
To make your own server, it must listen for a POST request, which
|
To make your own server, it must listen for a POST request, which
|
||||||
will consist of a JSON body, with the "image" field as a base64
|
will consist of a JSON body, with the "image" field as a base64
|
||||||
encoded string of a 24bit-BMP that the will be translated. The server
|
encoded string of a 24bit-BMP/PNG that the will be translated.
|
||||||
must output the translated image in the form of a JSON body, with
|
The server must output the translated image in the form of a
|
||||||
the "image" field also as a base64 encoded 24bit-BMP, or
|
JSON body, with the "image" field also as a base64 encoded
|
||||||
as an alpha channel png.
|
24bit-BMP, or as an alpha channel png.
|
||||||
*/
|
*/
|
||||||
static bool run_translation_service(void)
|
static bool run_translation_service(void)
|
||||||
{
|
{
|
||||||
@ -3194,11 +3272,37 @@ static bool run_translation_service(void)
|
|||||||
const char *rf2 = "\"}\0";
|
const char *rf2 = "\"}\0";
|
||||||
char *rf3 = NULL;
|
char *rf3 = NULL;
|
||||||
bool TRANSLATE_USE_BMP = false;
|
bool TRANSLATE_USE_BMP = false;
|
||||||
|
bool use_overlay = true;
|
||||||
|
|
||||||
const char *label = NULL;
|
const char *label = NULL;
|
||||||
char* system_label = NULL;
|
char* system_label = NULL;
|
||||||
core_info_t *core_info = NULL;
|
core_info_t *core_info = NULL;
|
||||||
|
|
||||||
|
#ifdef HAVE_MENU_WIDGETS
|
||||||
|
if (menu_widgets_ai_service_overlay_get_state() != 0)
|
||||||
|
{
|
||||||
|
/* For the case when ai service pause is disabled. */
|
||||||
|
menu_widgets_ai_service_overlay_unload();
|
||||||
|
goto finish;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (!settings->bools.ai_service_pause)
|
||||||
|
{
|
||||||
|
RARCH_LOG("Pause toggle not supported without menu widgets.\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_MENU_WIDGETS
|
||||||
|
if (video_driver_poke
|
||||||
|
&& video_driver_poke->load_texture && video_driver_poke->unload_texture)
|
||||||
|
{
|
||||||
|
use_overlay = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
use_overlay = false;
|
||||||
|
|
||||||
|
|
||||||
/* get the core info here so we can pass long the game name */
|
/* get the core info here so we can pass long the game name */
|
||||||
core_info_get_current_core(&core_info);
|
core_info_get_current_core(&core_info);
|
||||||
|
|
||||||
@ -3264,16 +3368,29 @@ static bool run_translation_service(void)
|
|||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
if (!video_driver_read_viewport(bit24_image_prev, false))
|
if (!video_driver_read_viewport(bit24_image_prev, false))
|
||||||
|
{
|
||||||
|
RARCH_LOG("Could not read viewport for translation service...\n");
|
||||||
goto finish;
|
goto finish;
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO: Rescale down to regular resolution */
|
/* TODO: Rescale down to regular resolution */
|
||||||
width = vp.width;
|
scaler->in_fmt = SCALER_FMT_BGR24;
|
||||||
height = vp.height;
|
scaler->out_fmt = SCALER_FMT_BGR24;
|
||||||
bit24_image = bit24_image_prev;
|
scaler->scaler_type = SCALER_TYPE_POINT;
|
||||||
bit24_image_prev = NULL;
|
scaler->in_width = vp.width;
|
||||||
|
scaler->in_height = vp.height;
|
||||||
|
scaler->out_width = width;
|
||||||
|
scaler->out_height = height;
|
||||||
|
scaler_ctx_gen_filter(scaler);
|
||||||
|
|
||||||
|
scaler->in_stride = vp.width*3;
|
||||||
|
scaler->out_stride = width*3;
|
||||||
|
scaler_ctx_scale_direct(scaler, bit24_image, bit24_image_prev);
|
||||||
|
scaler_ctx_gen_reset(scaler);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/* This is a software core, so just change the pixel format to 24-bit. */
|
||||||
bit24_image = (uint8_t*)malloc(width * height * 3);
|
bit24_image = (uint8_t*)malloc(width * height * 3);
|
||||||
if (!bit24_image)
|
if (!bit24_image)
|
||||||
goto finish;
|
goto finish;
|
||||||
@ -3298,13 +3415,14 @@ static bool run_translation_service(void)
|
|||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TRANSLATE_USE_BMP)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
At this point, we should have a screenshot in the buffer, so allocate
|
At this point, we should have a screenshot in the buffer, so allocate
|
||||||
an array to contain the BMP image along with the BMP header as bytes,
|
an array to contain the BMP image along with the BMP header as bytes,
|
||||||
and then covert that to a b64 encoded array for transport in JSON.
|
and then covert that to a b64 encoded array for transport in JSON.
|
||||||
*/
|
*/
|
||||||
if (TRANSLATE_USE_BMP)
|
|
||||||
{
|
|
||||||
form_bmp_header(header, width, height, false);
|
form_bmp_header(header, width, height, false);
|
||||||
bmp_buffer = (uint8_t*)malloc(width * height * 3+54);
|
bmp_buffer = (uint8_t*)malloc(width * height * 3+54);
|
||||||
if (!bmp_buffer)
|
if (!bmp_buffer)
|
||||||
@ -3355,7 +3473,7 @@ static bool run_translation_service(void)
|
|||||||
memcpy(json_buffer+11+out_length, (const void*)rf3, (16+strlen(system_label))*sizeof(uint8_t));
|
memcpy(json_buffer+11+out_length, (const void*)rf3, (16+strlen(system_label))*sizeof(uint8_t));
|
||||||
else
|
else
|
||||||
memcpy(json_buffer+11+out_length, (const void*)rf2, 3*sizeof(uint8_t));
|
memcpy(json_buffer+11+out_length, (const void*)rf2, 3*sizeof(uint8_t));
|
||||||
|
RARCH_LOG("Request size: %d\n", out_length);
|
||||||
{
|
{
|
||||||
char separator = '?';
|
char separator = '?';
|
||||||
char new_ai_service_url[PATH_MAX_LENGTH];
|
char new_ai_service_url[PATH_MAX_LENGTH];
|
||||||
@ -3409,9 +3527,23 @@ static bool run_translation_service(void)
|
|||||||
|
|
||||||
/*"image" is included for backwards compatability with
|
/*"image" is included for backwards compatability with
|
||||||
* vgtranslate < 1.04 */
|
* vgtranslate < 1.04 */
|
||||||
char* mode_chr = "image,png";
|
char* mode_chr;
|
||||||
if (settings->uints.ai_service_mode == 1)
|
if (settings->uints.ai_service_mode == 0)
|
||||||
|
{
|
||||||
|
if (use_overlay)
|
||||||
|
mode_chr = "image,png,png-a";
|
||||||
|
else
|
||||||
|
mode_chr = "image,png";
|
||||||
|
}
|
||||||
|
else if (settings->uints.ai_service_mode == 1)
|
||||||
mode_chr = "sound,wav";
|
mode_chr = "sound,wav";
|
||||||
|
else if (settings->uints.ai_service_mode == 2)
|
||||||
|
{
|
||||||
|
if (use_overlay)
|
||||||
|
mode_chr = "image,png,png-a,sound,wav";
|
||||||
|
else
|
||||||
|
mode_chr = "image,png,sound,wav";
|
||||||
|
}
|
||||||
|
|
||||||
snprintf(temp_string,
|
snprintf(temp_string,
|
||||||
sizeof(temp_string),
|
sizeof(temp_string),
|
||||||
@ -3421,7 +3553,7 @@ static bool run_translation_service(void)
|
|||||||
strlcat(new_ai_service_url, temp_string,
|
strlcat(new_ai_service_url, temp_string,
|
||||||
sizeof(new_ai_service_url));
|
sizeof(new_ai_service_url));
|
||||||
}
|
}
|
||||||
|
RARCH_LOG("SENDING... %s\n", new_ai_service_url);
|
||||||
task_push_http_post_transfer(new_ai_service_url,
|
task_push_http_post_transfer(new_ai_service_url,
|
||||||
json_buffer, true, NULL, handle_translation_cb, NULL);
|
json_buffer, true, NULL, handle_translation_cb, NULL);
|
||||||
}
|
}
|
||||||
@ -4625,7 +4757,6 @@ static void retroarch_pause_checks(void)
|
|||||||
if (is_paused)
|
if (is_paused)
|
||||||
{
|
{
|
||||||
RARCH_LOG("%s\n", msg_hash_to_str(MSG_PAUSED));
|
RARCH_LOG("%s\n", msg_hash_to_str(MSG_PAUSED));
|
||||||
command_event(CMD_EVENT_AUDIO_STOP, NULL);
|
|
||||||
|
|
||||||
#if defined(HAVE_MENU) && defined(HAVE_MENU_WIDGETS)
|
#if defined(HAVE_MENU) && defined(HAVE_MENU_WIDGETS)
|
||||||
if (menu_widgets_inited)
|
if (menu_widgets_inited)
|
||||||
@ -4652,8 +4783,13 @@ static void retroarch_pause_checks(void)
|
|||||||
menu_widgets_paused = is_paused;
|
menu_widgets_paused = is_paused;
|
||||||
#endif
|
#endif
|
||||||
RARCH_LOG("%s\n", msg_hash_to_str(MSG_UNPAUSED));
|
RARCH_LOG("%s\n", msg_hash_to_str(MSG_UNPAUSED));
|
||||||
command_event(CMD_EVENT_AUDIO_START, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_MENU_WIDGETS
|
||||||
|
if (menu_widgets_ai_service_overlay_get_state() == 1)
|
||||||
|
menu_widgets_ai_service_overlay_unload();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void retroarch_frame_time_free(void)
|
static void retroarch_frame_time_free(void)
|
||||||
@ -4749,23 +4885,26 @@ bool command_event(enum event_command cmd, void *data)
|
|||||||
{
|
{
|
||||||
#ifdef HAVE_TRANSLATE
|
#ifdef HAVE_TRANSLATE
|
||||||
settings_t *settings = configuration_settings;
|
settings_t *settings = configuration_settings;
|
||||||
if (settings->uints.ai_service_mode == 0)
|
if (settings->bools.ai_service_pause)
|
||||||
{
|
{
|
||||||
/* Default mode - pause on call, unpause on second press. */
|
/* pause on call, unpause on second press. */
|
||||||
if (!runloop_paused)
|
if (!runloop_paused)
|
||||||
{
|
{
|
||||||
command_event(CMD_EVENT_PAUSE, NULL);
|
command_event(CMD_EVENT_PAUSE, NULL);
|
||||||
command_event(CMD_EVENT_AI_SERVICE_CALL, NULL);
|
command_event(CMD_EVENT_AI_SERVICE_CALL, NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
command_event(CMD_EVENT_UNPAUSE, NULL);
|
command_event(CMD_EVENT_UNPAUSE, NULL);
|
||||||
}
|
}
|
||||||
/* Text-to-Speech mode - don't pause */
|
}
|
||||||
else if (settings->uints.ai_service_mode == 1)
|
|
||||||
command_event(CMD_EVENT_AI_SERVICE_CALL, NULL);
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
RARCH_LOG("Invalid AI Service Mode.\n");
|
/* Don't pause - useful for Text-To-Speech since
|
||||||
|
* the audio can't currently play while paused.
|
||||||
|
* Also useful for cases when users don't want the
|
||||||
|
* core's sound to stop while translating. */
|
||||||
|
command_event(CMD_EVENT_AI_SERVICE_CALL, NULL);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
@ -24849,6 +24988,14 @@ static enum runloop_state runloop_check_state(void)
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_MENU_WIDGETS
|
||||||
|
if (menu_widgets_ai_service_overlay_get_state() == 3)
|
||||||
|
{
|
||||||
|
command_event(CMD_EVENT_PAUSE, NULL);
|
||||||
|
menu_widgets_ai_service_overlay_set_state(1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBNX
|
#ifdef HAVE_LIBNX
|
||||||
/* Should be called once per frame */
|
/* Should be called once per frame */
|
||||||
if (!appletMainLoop())
|
if (!appletMainLoop())
|
||||||
|
Loading…
Reference in New Issue
Block a user