7#if defined(SDL_LIBRETRO_IMPLEMENTATION) && !defined(SDL_LIBRETRO_MESSAGES_IMPL_ONCE)
8#define SDL_LIBRETRO_MESSAGES_IMPL_ONCE
10static void SDL_Libretro_OsdPush(SDL_Libretro* lr,
const char* msg,
double durationSec,
unsigned priority,
enum retro_message_type type, int8_t progress) {
11 if (!lr || !msg || msg[0] ==
'\0')
return;
13 Uint64 endMs = SDL_GetTicks() + (Uint64)(durationSec * 1000.0);
15 for (
int i = 0; i < lr->osdQueueCount; i++) {
16 if (lr->osdQueue[i].msg && SDL_strcmp(lr->osdQueue[i].msg, msg) == 0) {
17 lr->osdQueue[i].endTimeMs = endMs;
18 lr->osdQueue[i].priority = priority;
19 lr->osdQueue[i].type = type;
20 lr->osdQueue[i].progress = progress;
25 Uint64 now = SDL_GetTicks();
27 for (
int i = 0; i < lr->osdQueueCount; i++) {
28 if (now > lr->osdQueue[i].endTimeMs) {
29 SDL_free(lr->osdQueue[i].msg);
30 lr->osdQueue[i].msg = NULL;
37 if (lr->osdQueueCount >= lr->osdQueueCapacity) {
38 int newCap = lr->osdQueueCapacity ? lr->osdQueueCapacity * 2 : SDL_LIBRETRO_OSD_INITIAL_CAPACITY;
39 SDL_LibretroOsdEntry* newQueue = (SDL_LibretroOsdEntry*)SDL_realloc(lr->osdQueue, (
size_t)newCap *
sizeof(SDL_LibretroOsdEntry));
40 if (!newQueue)
return;
41 lr->osdQueue = newQueue;
42 lr->osdQueueCapacity = newCap;
44 slot = lr->osdQueueCount++;
46 lr->osdQueue[slot].msg = SDL_strdup(msg);
47 lr->osdQueue[slot].endTimeMs = endMs;
48 lr->osdQueue[slot].priority = priority;
49 lr->osdQueue[slot].type = type;
50 lr->osdQueue[slot].progress = progress;
53static int SDL_Libretro_OsdFindTop(SDL_Libretro* lr) {
54 Uint64 now = SDL_GetTicks();
59 for (
int i = 0; i < lr->osdQueueCount; i++) {
60 if (now > lr->osdQueue[i].endTimeMs) {
61 SDL_free(lr->osdQueue[i].msg);
62 lr->osdQueue[i].msg = NULL;
65 if (dst != i) lr->osdQueue[dst] = lr->osdQueue[i];
66 if (best == -1 || lr->osdQueue[dst].priority > bestPri) {
67 bestPri = lr->osdQueue[dst].priority;
72 lr->osdQueueCount = dst;
76static void SDL_Libretro_FreeMessages(SDL_Libretro* lr) {
77 for (
int i = 0; i < lr->osdQueueCount; i++) {
78 SDL_free(lr->osdQueue[i].msg);
80 SDL_free(lr->osdQueue);
82 lr->osdQueueCount = 0;
83 lr->osdQueueCapacity = 0;
91 if (!msg || msg[0] ==
'\0') {
92 for (
int i = 0; i < lr->osdQueueCount; i++) {
93 SDL_free(lr->osdQueue[i].msg);
95 lr->osdQueueCount = 0;
98 SDL_Libretro_OsdPush(lr, msg, duration, 0, RETRO_MESSAGE_TYPE_NOTIFICATION, -1);
105 if (!lr || lr->osdQueueCount == 0)
return NULL;
106 int top = SDL_Libretro_OsdFindTop(lr);
107 if (top < 0)
return NULL;
108 return lr->osdQueue[top].msg;
111int SDL_Libretro_GetMessageProgress(SDL_Libretro* lr) {
112 if (!lr || lr->osdQueueCount == 0)
return -1;
113 int top = SDL_Libretro_OsdFindTop(lr);
114 if (top < 0)
return -1;
115 return lr->osdQueue[top].progress;
118int SDL_Libretro_GetMessageType(SDL_Libretro* lr) {
119 if (!lr || lr->osdQueueCount == 0)
return 0;
120 int top = SDL_Libretro_OsdFindTop(lr);
121 if (top < 0)
return 0;
122 return (
int)lr->osdQueue[top].type;
125unsigned SDL_Libretro_GetMessageCount(SDL_Libretro* lr) {
126 if (!lr || lr->osdQueueCount == 0)
return 0;
127 SDL_Libretro_OsdFindTop(lr);
128 return (
unsigned)lr->osdQueueCount;
131bool SDL_Libretro_GetMessageByIndex(SDL_Libretro* lr,
unsigned index,
132 const char** msg,
int* progress,
int* type) {
133 if (!lr)
return false;
134 SDL_Libretro_OsdFindTop(lr);
135 if (index >= (
unsigned)lr->osdQueueCount)
return false;
136 if (msg) *msg = lr->osdQueue[index].msg;
137 if (progress) *progress = lr->osdQueue[index].progress;
138 if (type) *type = (int)lr->osdQueue[index].type;
void SDL_Libretro_SetMessage(SDL_Libretro *lr, const char *msg, double duration)
Add a message to be displayed within the libretro context.
const char * SDL_Libretro_GetMessage(SDL_Libretro *lr)
Gets the most relevent libretro message to display from the queue.