Skip to content

Commit d75d53c

Browse files
authored
AI service: Add Apple on-device OCR/Translation (#18671)
1 parent c7af98a commit d75d53c

14 files changed

Lines changed: 1691 additions & 249 deletions

File tree

accessibility.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,20 @@ bool is_narrator_running(bool accessibility_enable);
8282
*/
8383
bool run_translation_service(settings_t *settings, bool paused);
8484

85+
/**
86+
* config_get_ai_service_backend_options:
87+
*
88+
* Get available AI service backends separated by '|'.
89+
**/
90+
const char *config_get_ai_service_backend_options(void);
91+
92+
/**
93+
* config_get_default_ai_service_backend:
94+
*
95+
* Get the default AI service backend identifier.
96+
**/
97+
const char *config_get_default_ai_service_backend(void);
98+
8599
bool accessibility_speak_priority(
86100
bool accessibility_enable,
87101
unsigned accessibility_narrator_speech_speed,

configuration.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353

5454
#include "tasks/task_content.h"
5555
#include "tasks/tasks_internal.h"
56+
#include "accessibility.h"
5657

5758
#include "list_special.h"
5859

@@ -1556,6 +1557,7 @@ static struct config_array_setting *populate_settings_array(
15561557
SETTING_ARRAY("midi_driver", settings->arrays.midi_driver, false, NULL, true);
15571558
SETTING_ARRAY("midi_input", settings->arrays.midi_input, true, DEFAULT_MIDI_INPUT, true);
15581559
SETTING_ARRAY("midi_output", settings->arrays.midi_output, true, DEFAULT_MIDI_OUTPUT, true);
1560+
SETTING_ARRAY("ai_service_backend", settings->arrays.ai_service_backend, false, NULL, true);
15591561

15601562
SETTING_ARRAY("video_driver", settings->arrays.video_driver, false, NULL, true);
15611563
SETTING_ARRAY("video_context_driver", settings->arrays.video_context_driver, false, NULL, true);
@@ -2855,6 +2857,9 @@ void config_set_defaults(void *data)
28552857
const char *def_location = config_get_default_location();
28562858
const char *def_record = config_get_default_record();
28572859
const char *def_midi = config_get_default_midi();
2860+
#ifdef HAVE_TRANSLATE
2861+
const char *def_ai_service_backend = config_get_default_ai_service_backend();
2862+
#endif
28582863
const char *def_mitm = DEFAULT_NETPLAY_MITM_SERVER;
28592864
struct video_viewport *custom_vp = &settings->video_vp_custom;
28602865
struct config_float_setting *float_settings = populate_settings_float (settings, &float_settings_size);
@@ -2938,6 +2943,12 @@ void config_set_defaults(void *data)
29382943
configuration_set_string(settings,
29392944
settings->arrays.cloud_sync_driver,
29402945
def_cloudsync);
2946+
#ifdef HAVE_TRANSLATE
2947+
if (def_ai_service_backend)
2948+
configuration_set_string(settings,
2949+
settings->arrays.ai_service_backend,
2950+
def_ai_service_backend);
2951+
#endif
29412952
if (def_location)
29422953
configuration_set_string(settings,
29432954
settings->arrays.location_driver,

configuration.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,7 @@ typedef struct settings
512512
char midi_driver[32];
513513
char midi_input[32];
514514
char midi_output[32];
515+
char ai_service_backend[32];
515516
#ifdef HAVE_LAKKA
516517
char cpu_main_gov[32];
517518
char cpu_menu_gov[32];

intl/msg_hash_us.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7376,6 +7376,14 @@ MSG_HASH(
73767376
MENU_ENUM_SUBLABEL_AI_SERVICE_MODE,
73777377
"Show translation as a text overlay (Image Mode), play as Text-To-Speech (Speech), or use a system narrator like NVDA (Narrator)."
73787378
)
7379+
MSG_HASH(
7380+
MENU_ENUM_LABEL_VALUE_AI_SERVICE_BACKEND,
7381+
"AI Service Backend"
7382+
)
7383+
MSG_HASH(
7384+
MENU_ENUM_SUBLABEL_AI_SERVICE_BACKEND,
7385+
"Select which translation backend to use. HTTP uses a remote server at the configured URL. Apple uses on-device OCR and translation (macOS/iOS)."
7386+
)
73797387
MSG_HASH(
73807388
MENU_ENUM_LABEL_VALUE_AI_SERVICE_URL,
73817389
"AI Service URL"

menu/cbs/menu_cbs_sublabel.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_user_interface_settings_list, MENU_
277277
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_ai_service_settings_list, MENU_ENUM_SUBLABEL_AI_SERVICE_SETTINGS)
278278
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_accessibility_settings_list, MENU_ENUM_SUBLABEL_ACCESSIBILITY_SETTINGS)
279279
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_ai_service_mode, MENU_ENUM_SUBLABEL_AI_SERVICE_MODE)
280+
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_ai_service_backend, MENU_ENUM_SUBLABEL_AI_SERVICE_BACKEND)
280281
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_ai_service_pause, MENU_ENUM_SUBLABEL_AI_SERVICE_PAUSE)
281282
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_ai_service_target_lang, MENU_ENUM_SUBLABEL_AI_SERVICE_TARGET_LANG)
282283
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_ai_service_source_lang, MENU_ENUM_SUBLABEL_AI_SERVICE_SOURCE_LANG)
@@ -5437,6 +5438,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
54375438
case MENU_ENUM_LABEL_AI_SERVICE_MODE:
54385439
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_ai_service_mode);
54395440
break;
5441+
case MENU_ENUM_LABEL_AI_SERVICE_BACKEND:
5442+
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_ai_service_backend);
5443+
break;
54405444
case MENU_ENUM_LABEL_AI_SERVICE_PAUSE:
54415445
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_ai_service_pause);
54425446
break;

menu/menu_displaylist.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8515,6 +8515,7 @@ unsigned menu_displaylist_build_list(
85158515
{MENU_ENUM_LABEL_AI_SERVICE_ENABLE, PARSE_ONLY_BOOL, true},
85168516
{MENU_ENUM_LABEL_AI_SERVICE_MODE, PARSE_ONLY_UINT, false},
85178517
{MENU_ENUM_LABEL_AI_SERVICE_URL, PARSE_ONLY_STRING, false},
8518+
{MENU_ENUM_LABEL_AI_SERVICE_BACKEND, PARSE_ONLY_STRING_OPTIONS, false},
85188519
{MENU_ENUM_LABEL_AI_SERVICE_PAUSE, PARSE_ONLY_BOOL, false},
85198520
{MENU_ENUM_LABEL_AI_SERVICE_SOURCE_LANG, PARSE_ONLY_UINT, false},
85208521
{MENU_ENUM_LABEL_AI_SERVICE_TARGET_LANG, PARSE_ONLY_UINT, false},
@@ -8525,6 +8526,7 @@ unsigned menu_displaylist_build_list(
85258526
switch (build_list[i].enum_idx)
85268527
{
85278528
case MENU_ENUM_LABEL_AI_SERVICE_MODE:
8529+
case MENU_ENUM_LABEL_AI_SERVICE_BACKEND:
85288530
case MENU_ENUM_LABEL_AI_SERVICE_URL:
85298531
case MENU_ENUM_LABEL_AI_SERVICE_PAUSE:
85308532
case MENU_ENUM_LABEL_AI_SERVICE_SOURCE_LANG:

menu/menu_setting.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@
9999
#include "../network/cloud_sync_driver.h"
100100
#include "../record/record_driver.h"
101101
#include "../tasks/tasks_internal.h"
102+
#include "../accessibility.h"
102103
#include "../config.def.h"
103104
#include "../ui/ui_companion_driver.h"
104105
#include "../performance_counters.h"
@@ -21100,6 +21101,23 @@ static bool setting_append_list(
2110021101
(*list)[list_info->index - 1].action_ok = &setting_action_ok_uint;
2110121102
menu_settings_list_current_add_range(list, list_info, 0, 2, 1, true, true);
2110221103

21104+
CONFIG_STRING_OPTIONS(
21105+
list, list_info,
21106+
settings->arrays.ai_service_backend,
21107+
sizeof(settings->arrays.ai_service_backend),
21108+
MENU_ENUM_LABEL_AI_SERVICE_BACKEND,
21109+
MENU_ENUM_LABEL_VALUE_AI_SERVICE_BACKEND,
21110+
config_get_default_ai_service_backend(),
21111+
strdup(config_get_ai_service_backend_options()),
21112+
&group_info,
21113+
&subgroup_info,
21114+
parent_group,
21115+
general_write_handler,
21116+
general_read_handler);
21117+
(*list)[list_info->index - 1].action_ok = setting_action_ok_uint;
21118+
(*list)[list_info->index - 1].action_left = setting_string_action_left_driver;
21119+
(*list)[list_info->index - 1].action_right = setting_string_action_right_driver;
21120+
2110321121
CONFIG_STRING(
2110421122
list, list_info,
2110521123
settings->arrays.ai_service_url,

msg_hash.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2997,6 +2997,7 @@ enum msg_hash_enums
29972997
MENU_LABEL(ACCESSIBILITY_NARRATOR_SPEECH_SPEED),
29982998
MENU_LABEL(AI_SERVICE_SETTINGS),
29992999
MENU_LABEL(AI_SERVICE_MODE),
3000+
MENU_LABEL(AI_SERVICE_BACKEND),
30003001
MENU_LABEL(AI_SERVICE_TARGET_LANG),
30013002
MENU_LABEL(AI_SERVICE_SOURCE_LANG),
30023003
MENU_LABEL(AI_SERVICE_URL),

pkg/apple/BaseConfig.xcconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ OTHER_CFLAGS = $(inherited) -DHAVE_SWIFT
8181
OTHER_CFLAGS = $(inherited) -DHAVE_THREADS
8282
OTHER_CFLAGS = $(inherited) -DHAVE_THREAD_STORAGE
8383
OTHER_CFLAGS = $(inherited) -DHAVE_TRANSLATE
84+
OTHER_CFLAGS = $(inherited) -DHAVE_TRANSLATE_APPLE
8485
OTHER_CFLAGS = $(inherited) -DHAVE_UPDATE_ASSETS
8586
OTHER_CFLAGS = $(inherited) -DHAVE_UPDATE_CORE_INFO
8687
OTHER_CFLAGS = $(inherited) -DHAVE_VIDEO_FILTER

pkg/apple/RetroArch_Metal.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,10 @@
9494
07B9B9802E49A7A3007E419E /* RetroArchAppShortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B9B97D2E49A7A3007E419E /* RetroArchAppShortcuts.swift */; };
9595
07B9B9812E49A7A3007E419E /* RetroArchAppShortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B9B97D2E49A7A3007E419E /* RetroArchAppShortcuts.swift */; };
9696
07B9B9822E49A7A3007E419E /* RetroArchAppShortcuts.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07B9B97D2E49A7A3007E419E /* RetroArchAppShortcuts.swift */; };
97+
07ATRANS032025010700000003 /* AppleTranslateBackend.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07ATRANS012025010700000001 /* AppleTranslateBackend.swift */; };
98+
07ATRANS042025010700000004 /* AppleTranslateBackend.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07ATRANS012025010700000001 /* AppleTranslateBackend.swift */; };
99+
07ATRANS052025010700000005 /* AppleTranslateBackend.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07ATRANS012025010700000001 /* AppleTranslateBackend.swift */; };
100+
07ATRANS062025010700000006 /* AppleTranslateBackend.swift in Sources */ = {isa = PBXBuildFile; fileRef = 07ATRANS012025010700000001 /* AppleTranslateBackend.swift */; };
97101
07D851CD2CAF06E2005097EA /* CloudKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 075650242C488918004C5E7E /* CloudKit.framework */; };
98102
07F2BBC62BE83A4700FD1295 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 089C165CFE840E0CC02AAC07 /* InfoPlist.strings */; };
99103
07F2BBC82BE83A4700FD1295 /* assets.zip in Resources */ = {isa = PBXBuildFile; fileRef = 9254B33025FA0BA300A1E0DA /* assets.zip */; };
@@ -267,6 +271,8 @@
267271
05A8C5BA20DB72F000FF7857 /* ui_cocoa.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ui_cocoa.m; sourceTree = "<group>"; };
268272
05A8C5BD20DB72F000FF7857 /* cocoa_common.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = cocoa_common.m; sourceTree = "<group>"; };
269273
05A8C5C220DB72F000FF7857 /* cocoa_common.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = cocoa_common.h; sourceTree = "<group>"; };
274+
07ATRANS012025010700000001 /* AppleTranslateBackend.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppleTranslateBackend.swift; sourceTree = "<group>"; };
275+
07ATRANS022025010700000002 /* translation_driver_apple.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = translation_driver_apple.h; sourceTree = "<group>"; };
270276
05A8C5C820DB72F000FF7857 /* ui_qt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ui_qt.h; sourceTree = "<group>"; };
271277
05A8C5CE20DB72F000FF7857 /* ui_cocoa.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ui_cocoa.h; sourceTree = "<group>"; };
272278
05A8C5CF20DB72F000FF7857 /* ui_cocoatouch.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ui_cocoatouch.m; sourceTree = "<group>"; };
@@ -854,8 +860,10 @@
854860
05A8C5BB20DB72F000FF7857 /* cocoa */ = {
855861
isa = PBXGroup;
856862
children = (
863+
07ATRANS012025010700000001 /* AppleTranslateBackend.swift */,
857864
05A8C5C220DB72F000FF7857 /* cocoa_common.h */,
858865
05A8C5BD20DB72F000FF7857 /* cocoa_common.m */,
866+
07ATRANS022025010700000002 /* translation_driver_apple.h */,
859867
);
860868
path = cocoa;
861869
sourceTree = "<group>";
@@ -1681,6 +1689,7 @@
16811689
isa = PBXSourcesBuildPhase;
16821690
buildActionMask = 2147483647;
16831691
files = (
1692+
07ATRANS032025010700000003 /* AppleTranslateBackend.swift in Sources */,
16841693
07B9B97F2E49A7A3007E419E /* RetroArchAppShortcuts.swift in Sources */,
16851694
05422E432140C8DB00F09961 /* griffin_glslang.cpp in Sources */,
16861695
05422E442140C8DB00F09961 /* menu_pipeline.metal in Sources */,
@@ -1696,6 +1705,7 @@
16961705
isa = PBXSourcesBuildPhase;
16971706
buildActionMask = 2147483647;
16981707
files = (
1708+
07ATRANS042025010700000004 /* AppleTranslateBackend.swift in Sources */,
16991709
07B9B9812E49A7A3007E419E /* RetroArchAppShortcuts.swift in Sources */,
17001710
0720994429B1258C001642BB /* griffin_glslang.cpp in Sources */,
17011711
0720994529B1258C001642BB /* menu_pipeline.metal in Sources */,
@@ -1711,6 +1721,7 @@
17111721
isa = PBXSourcesBuildPhase;
17121722
buildActionMask = 2147483647;
17131723
files = (
1724+
07ATRANS052025010700000005 /* AppleTranslateBackend.swift in Sources */,
17141725
07B9B9802E49A7A3007E419E /* RetroArchAppShortcuts.swift in Sources */,
17151726
07F2BBCC2BE83A4700FD1295 /* griffin_glslang.cpp in Sources */,
17161727
07F2BBCD2BE83A4700FD1295 /* menu_pipeline.metal in Sources */,
@@ -1726,6 +1737,7 @@
17261737
isa = PBXSourcesBuildPhase;
17271738
buildActionMask = 2147483647;
17281739
files = (
1740+
07ATRANS062025010700000006 /* AppleTranslateBackend.swift in Sources */,
17291741
07B9B9822E49A7A3007E419E /* RetroArchAppShortcuts.swift in Sources */,
17301742
05D7753720A567A700646447 /* griffin_glslang.cpp in Sources */,
17311743
05770B9920E805160013DABC /* menu_pipeline.metal in Sources */,

0 commit comments

Comments
 (0)