diff --git a/libretro-common/include/libretro.h b/libretro-common/include/libretro.h index f2d115b2d0..ff32ca2300 100644 --- a/libretro-common/include/libretro.h +++ b/libretro-common/include/libretro.h @@ -1288,6 +1288,36 @@ enum retro_mod * based systems). */ +#define RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION 59 + /* unsigned * -- + * Unsigned value is the API version number of the message + * interface supported by the frontend. If callback returns + * false, API version is assumed to be 0. + * + * In legacy code, messages may be displayed in an + * implementation-specific manner by passing a struct + * of type retro_message to RETRO_ENVIRONMENT_SET_MESSAGE. + * This may be still be done regardless of the message + * interface version. + * + * If version is >= 1 however, messages may instead be + * displayed by passing a struct of type retro_message_ext + * to RETRO_ENVIRONMENT_SET_MESSAGE_EXT. This allows the + * core to specify message logging level, priority and + * destination (OSD, logging interface or both). + */ + +#define RETRO_ENVIRONMENT_SET_MESSAGE_EXT 60 + /* const struct retro_message_ext * -- + * Sets a message to be displayed in an implementation-specific + * manner for a certain amount of 'frames'. Additionally allows + * the core to specify message logging level, priority and + * destination (OSD, logging interface or both). + * Should not be used for trivial messages, which should simply be + * logged via RETRO_ENVIRONMENT_GET_LOG_INTERFACE (or as a + * fallback, stderr). + */ + /* VFS functionality */ /* File paths: @@ -2507,6 +2537,22 @@ struct retro_message unsigned frames; /* Duration in frames of message. */ }; +enum retro_message_target +{ + RETRO_MESSAGE_TARGET_ALL = 0, + RETRO_MESSAGE_TARGET_OSD, + RETRO_MESSAGE_TARGET_LOG +}; + +struct retro_message_ext +{ + const char *msg; /* Message to be displayed/logged */ + unsigned frames; /* Duration in frames of message when targeting OSD */ + unsigned priority; /* Message priority when targeting OSD */ + enum retro_log_level level; /* Message logging level (info, warn, etc.) */ + enum retro_message_target target; /* Message destination: OSD, logging interface or both */ +}; + /* Describes how the libretro implementation maps a libretro input bind * to its internal input system through a human readable string. * This string can be used to better let a user configure input. */ diff --git a/retroarch.c b/retroarch.c index 37ec1a9979..7b3814dc99 100644 --- a/retroarch.c +++ b/retroarch.c @@ -10301,6 +10301,11 @@ static bool rarch_environment_cb(unsigned cmd, void *data) break; + case RETRO_ENVIRONMENT_GET_MESSAGE_INTERFACE_VERSION: + /* Current API version is 1 */ + *(unsigned *)data = 1; + break; + case RETRO_ENVIRONMENT_SET_MESSAGE: { const struct retro_message *msg = (const struct retro_message*)data; @@ -10317,6 +10322,74 @@ static bool rarch_environment_cb(unsigned cmd, void *data) break; } + case RETRO_ENVIRONMENT_SET_MESSAGE_EXT: + { + const struct retro_message_ext *msg = (const struct retro_message_ext*)data; + + /* Log message, if required */ + if (msg->target != RETRO_MESSAGE_TARGET_OSD) + { + switch (msg->level) + { + case RETRO_LOG_DEBUG: + { + settings_t *settings = configuration_settings; + unsigned log_level = settings->uints.frontend_log_level; + + if (log_level == RETRO_LOG_DEBUG) + RARCH_LOG("[Environ]: SET_MESSAGE_EXT: %s\n", msg->msg); + } + break; + case RETRO_LOG_WARN: + RARCH_WARN("[Environ]: SET_MESSAGE_EXT: %s\n", msg->msg); + break; + case RETRO_LOG_ERROR: + RARCH_ERR("[Environ]: SET_MESSAGE_EXT: %s\n", msg->msg); + break; + case RETRO_LOG_INFO: + default: + RARCH_LOG("[Environ]: SET_MESSAGE_EXT: %s\n", msg->msg); + break; + } + } + + /* Display message via OSD, if required */ + if (msg->target != RETRO_MESSAGE_TARGET_LOG) + { +#if defined(HAVE_GFX_WIDGETS) + if (gfx_widgets_active()) + gfx_widget_set_libretro_message(msg->msg, + roundf((float)msg->frames / 60.0f * 1000.0f)); + else +#endif + { + enum message_queue_category category; + + switch (msg->level) + { + case RETRO_LOG_WARN: + category = MESSAGE_QUEUE_CATEGORY_WARNING; + break; + case RETRO_LOG_ERROR: + category = MESSAGE_QUEUE_CATEGORY_ERROR; + break; + case RETRO_LOG_INFO: + case RETRO_LOG_DEBUG: + default: + category = MESSAGE_QUEUE_CATEGORY_INFO; + break; + } + + runloop_msg_queue_push(msg->msg, + msg->priority, msg->frames, + true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, + category); + } + } + + break; + } + case RETRO_ENVIRONMENT_SET_ROTATION: { unsigned rotation = *(const unsigned*)data;