mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-07 08:36:02 -10:00
* video: per-screen geometry for the headset's floating screens Each floating screen, by the core's logical screen id, gets its own offsets, yaw, pitch, roll, scale and visibility (video_screen_xr_t), applied on top of where the layout puts it. video_views_xr_reset gives the defaults and video_views_xr_normalize clamps each value to its range: offsets to 10 m either way, angles to 180 degrees, scale from 0.1 to 10. A planner given no screens uses the defaults, so nothing moves until a setting does. * configuration: save per-screen headset geometry video_screen<N>_xr_x, _y, _z, _yaw, _pitch, _roll, _scale and _visible keep each floating screen's adjustments for screen ids 1 to 8, and survive configuration overrides like the other video settings. A minimal save writes only the values that differ from the defaults. The video_screens settings sample checks the round trip and the override cases, and runs in the OpenXR input and Wine views jobs. The defaults fixture now links video_views.c, which the reset uses. * menu: per-screen controls for the headset's floating screens Stereo 3D & Screens gains Screen, which picks a floating screen by its logical id among those in the current frame's map, and for it Horizontal, Vertical and Depth Offset, Yaw, Pitch, Roll, Scale and Visible, with Reset Screen and Reset All Screens. The rows apply live and are hidden where they cannot apply, such as a tracked projection's eyes. Stepping between screens reads one snapshot of the map and is bounded, so a tracking change mid-step cannot leave it walking an empty map. docs/openxr.md describes the controls; the video_screens sample drives them through the shipping menu actions. * video: apply per-screen headset geometry to the frame snapshots Each XR planner, Vulkan's and GL's, takes the normalized screen settings with the frame snapshot, so a screen moves, turns, scales or hides as its rows change, while paused too; recentering and tracked projections are unaffected. Screen images are kept between frames, so shader feedback survives a placement change. A retained XR target that cannot be allocated is skipped quietly, remembered by its size so it is not retried every frame; only the desktop UI and canvas targets log the failure. Covered by openxr_core_test, the video_screens sample, the e2e runner's feedback shader case and the new vulkan_views_target sample. * android: keep the OpenXR EGL context C89 gl_xr_egl_init declared its extension string after statements. * video: pose inverse, layout spots and grab maths for headset edit mode Each item's layout spot comes from one helper that placement uses and the quad set records per slot, so a shown pose turns back into the settings that placed it. Grab maths: the item follows the aim, level unless tilting, offsets clamped to the settings' range; the stick pushes along the ray and resizes. Edit picking sees every item and takes the menu by a handle bar under it. * video: a frame without a view map is screen 1 in the headset A core without a views map (SNES, say) had no screen to select, so its frame could not be moved. Its whole frame now takes screen 1's offsets, turn, scale and visibility, and the selector lists Screen 1. gl's window stays as laid out while the menu is open over it. * video: the headset's menu in front of screen 1, or where it was put The menu sat at a fixed spot, so moving screen 1 closer left the menu behind it. It now floats 10 cm in front of screen 1, facing as it does, at its default angular size and never nearer than 0.4 m, while screen 1 floats and shows, and is still submitted after the screens. A menu place (video_openxr_menu_xr_* with video_openxr_menu_placed) overrides that; it is saved like the per-screen keys, and Reset All Screens clears it. * input: Edit Headset Screens mode for the OpenXR controllers Edit Screens starts from a hotkey, a headset action, the HEADSET_EDIT_SCREENS command or a Stereo 3D & Screens row, and stops on the same, on opening the menu, on a video reinit or when the session ends. It syncs its own action set in place of the game's, points the lasers at every item whatever the Laser Pointer setting, keeps the menu's quad up while editing, and with While Editing Screens set to Pause pauses only content that was running. A runtime that refuses its bindings keeps the game's and leaves edit mode unavailable. The setting reaches the headset's poll with the others, and the pause and resume are asked of the frontend as platform requests, so the input driver issues no command and takes no settings itself. A Laser Pointer value past its choices, which a hand-edited config can hold, reads as Auto rather than as edit mode's. * input: grab, tilt, push and resize headset screens in edit mode A grip on an item takes it in the screens' frame: it keeps its pose relative to the hand, stays level unless the trigger is held, and the stick pushes it along the laser and resizes it, past a deadzone. Each poll writes the item's offsets, turn and scale where the menu's rows write them, through named frontend calls, clamped so it waits at a limit and resumes from there. The menu is taken by its handle; a menu that follows screen 1 is placed as large as it shows. The main button resets a free item as Reset Screen does, or puts the menu back in front of screen 1. A recenter, a screen leaving the map and leaving edit mode let go, counted for the frame snapshot; an untracked hand holds its item still. * openxr: held screens follow the hand at the headset's rate The main thread publishes what each hand holds through a seqlock; each headset frame re-places a held item, both eyes of a stereo screen, from that frame's own aim, so it no longer waits for the next video frame. An item let go stays where the hand left it until a quad set planned at or after its release (an edit count carried in the frame snapshot) shows it, even once the hand holds another item, so nothing steps back. Lazy Follow holds its glide while anything is held. Edit mode outlines every item, brightly the one under a laser, and draws the menu's handle bar under it, from the laser's image, now an atlas of the dot, two outlines and two handle bars. They take only the layers the screens leave after the dots. * openxr: edit mode end-to-end cases and documentation The test layer's aim can roll, and the e2e runner drives edit mode against Monado: grabs that follow the hand on every headset frame and stay where they are let go, level and tilt, the stick, resets of a screen and of the menu, the menu taken by its handle and following Screen 1 at its size, outlines and the handle, a no-map core, a views core's fallback frame, Follow Head, Lazy Follow, recentering, two hands, pausing, and what starts and ends edit mode, including the headset's hotkey bits with no command interface. The cases whose work is a host's or driver's own run on glcore and gl too. docs/openxr.md explains editing screens in the headset and where the menu goes. * openxr: a laser beam from each controller to its dot A thin strip runs from each hand's aim to its dot, or 1.5 m into nothing, turned about its own axis each headset frame to face the head so it never shows edge on. It comes from the laser's image, so it needs no new swapchain, and uses layers left after the dots and edit mode's outlines, so it is the first to go when the runtime has few. The new Laser Beam setting shows it in edit mode only (the default), always, or never; outside edit mode, Laser Pointer and its hotkey hide it with the dot. * openxr: edit mode outlines in three bands, outside the item A light band between two dark ones shows on white, black and busy borders alike. The rim now sits wholly outside its item, 5 mm clear of it even after filtering, so it never covers the picture; its region grows to keep two texels a band at about the old thickness. Screens' outlines are submitted before the screens, so a neighbour placed flush covers the part of a rim over its picture, while the menu's outline and handle bar stay on top. The handle bar moves 5 mm below the menu's outline, which it would otherwise cover, and gets the same bands, faint and bright. * input: choose a headset edit item with Select Next and Previous Edit mode steps from the laser through the screens it can move and the menu. A chosen item is the one lit, either hand's grip takes it from wherever the hand is, and Reset resets it, so a screen hidden behind another can be moved. Whatever a hand holds stays lit. A ray on the menu's handle bar takes the menu before any screen in front of it. Within 3 cm of the bar, a ray that came from the bar keeps the menu even over a screen, and one that came from elsewhere takes it only where no screen is hit. * openxr: snap a held headset screen to the screens near it Snap to Screens, on by default, turns a held screen parallel or square to a nearby screen and lines up its plane, edges or centre. Each pull is exact within 3 cm or 5 degrees and fades out over as far again, so the screen catches up with the hand rather than jumping, and snapping fades in over the first 5 cm or 10 degrees after a grab, so taking a screen never moves it. With several screens near, the snap that leaves the least error wins, so a near screen's exact pull beats a far one's fading pull whatever their order. One stateless function inside the grab serves the main thread and the headset's thread, so a screen is saved where it was shown. The holding hand buzzes as a snap takes hold, once, and not again until the screen has left that pull. * input: turn a held headset item with the free hand's stick A quarter turn of a held screen needed the controller turned a quarter turn, which swung the screen round the hand on its long reach, so a square snap could not be reached. Now the stick of the hand holding nothing turns what the other hand holds about the vertical through its middle, faster the further it is pushed, and snapping still catches it parallel or square. A carried item keeps its pitch and roll and its angle to the way the hand points across the floor, so raising, lowering or twisting the hand no longer tips or swivels it; the trigger lets it ride the hand rigidly. * openxr: smooth the controller aim in edit mode A screen held about 2 m out on the laser magnified every tremor of the hand. In edit mode each hand's aim now goes through a One Euro filter, which smooths a slow hand hard and a fast one little, with its rate taken from the headset frame's own time step. The headset's thread filters once a frame and hands the result to the main thread, which grabs, moves and lets go from it, so a screen is saved where it was shown. The new Edit Smoothing setting picks Off, Low, Medium (the default) or High; outside edit mode the lasers are never smoothed. * openxr: name the chosen edit item beside the controller Edit mode now shows a faint tag just above the hand that last pressed Select Next or Previous, reading Laser, Screen N or Menu, so what the grip will take is plain without a notice. The words are drawn once into the laser's image in the default font and the interface language, light over a dark halo like the outlines so they read on any background, and the tag is one more headset layer; when the runtime is short of layers the beams are dropped before it. On a runtime whose swapchains are too narrow for the words, the laser's image keeps its old width and there is no tag. * input: tilt a held headset item with the free hand's stick In edit mode the free hand's stick already turns the item the other hand holds. Its up and down now tilt that item too, about the item's own left-right line through its middle, at the turn's rate and with no limit: up tips the top back, as when pushing a monitor's top back. It works whether the item is carried or rides the hand with the trigger held, and snaps as the turn does. Within about 25 degrees of left or right the stick only turns, and within about 25 degrees of up or down it only tilts, so a push meant for one does not drift into the other. Edit mode's starting notice lists the turn and tilt and stays about 8 seconds. * input: snap a turned or tilted headset item to angle steps While the free hand's stick turns or tilts a held item in edit mode, the item clicks into steps of the new Snap to Angles setting (15 degrees by default; 30, 45, 90 or Off), so it is easy to set straight. The turn counts from facing the user's head across the floor, the tilt from upright. Within about 2 degrees of a step the item holds there and the holding hand buzzes once; the stick's own angle keeps adding up, so pushing on leaves the step. Only the stick steps: carrying an item or tilting it with the trigger never clicks, and a snap to another screen that would engage wins over a step. * openxr: show the back of a headset screen turned away Runtimes draw only the front of a quad layer, so a screen or the menu turned away from the head vanished. When the head is behind a quad's plane, the frame now submits a plain dark panel in that quad's place: a solid grey cell of the laser's image, at the quad's size, turned to face the head. It takes the quad's own layer, so the layer count and cap are unchanged. Edit mode picks either face, so an item turned away stays grabbable, and its outline, handle and dot turn with its back. * input: keep a screen snap's angle once the free stick lets go A snap to another screen shows a held screen square or parallel to it, but the item's own angle stays where the stick or the hand took it, up to several degrees off. The next turn with the free hand's stick started from that hidden angle, so the screen left the snap early on one side, late on the other, and caught up with a lurch. Now, as the free stick returns to its deadzone and as a push starts, a snap engaged on the turn becomes the item's own angle: the carried turn, or the orientation the trigger tilts. A snap still fading in never does, since that would hop the screen into it. The place is left to the hand, and carrying alone never keeps the angle, so pointing still pulls a screen out of a snap. Letting go of the grip leaves the item where it shows, as before. * openxr: hinge a held headset screen to a neighbour's edge Snap to Screens now also hinges a held screen to another along a shared edge at any angle between them, so a DS or 3DS pair can be opened at a slant: an edge within 5 degrees of parallel to one of the other's, within 3 cm of its line and sharing some length with it, turns exactly parallel and moves onto it, centres or ends level, its angle left free. The pull fades in over the first 3 cm of shared length, so a screen slides off the end of the other's edge without a jump, and a diagonal neighbour never hinges. Screens that would overlap do not hinge; the pull is whole from flat to square and fades out folded shut. Flat and square snap as before and report a hinge at 0 and 90. A turn to the same screen pivots on the shared edge, so the edge stays on the line as the screen leaves flat or square. The snap still keeps nothing between calls; its result carries a hinge bit, and video_xr_snap_hinge also says which edge and line, for the stick to swing about. * input: swing a hinged headset screen about the shared edge While a held screen is hinged to another, the free hand's stick axis that turns nearest the shared edge, the tilt for a top or bottom edge and the turn for a side one, now swings it about that edge, so it stays attached; the other axis still turns or tilts it and can pull it off. Where the swing leaves it, angle and place, it stays as the stick lets go. Snap to Angles counts a hinged screen's steps from flat with the other screen. A hinge counts only while the screen's own edge is within its range, not when other snaps alone hold it on the line, so a swing never carries a screen round a line it is far from. A square corner is a side hinge at 90 degrees, so the turn stick there now swings the screen about the corner's edge. Main thread only; nothing new reaches the frame loop, which still shows the grab through video_xr_grab_pose. * openxr: leave a gap between hinged headset screens Edges that meet in edit mode, side by side, at a corner or hinged at any angle, now click to a set gap from within 1 cm and otherwise keep the gap the hand gives them, still hinged, up to 10 cm (letting go by 13). Screens no longer have to touch, which made them overlap. Each grab carries the gap, so the edit poll and the frame loop snap alike; until a setting sets it, it is 0. Pushed past touching, a hinged edge stops there for the first centimetre of the push, the stop fading out by 3 cm, and ticks once per push. A swing pivots on the held screen's own edge, so the gap keeps through it, and a commit keeps the hand's gap unless the click holds it. After a swing lets go past square, that stick axis and its steps keep pivoting on the same edge until the edge leaves the hinge's reach, so a flick past square and back does not creep. Of two neighbours within the 5 degree turn snap, the nearer edge wins the turn and the hinge, by one measure for every screen, so a screen stacked behind, one off the ends of the edge or a side wall at a corner never outranks a hinge the turn holds. * menu: add Hinge Gap for headset screens Hinge Gap (0, 1, 2, 3, 5 or 10 cm, default 2) sets the gap edit mode's Snap to Screens leaves between screens that meet edge to edge, side by side, at a corner or hinged. Edit mode takes it as it starts and gives it to each grab; the click to it buzzes like the other snaps. * menu: put Edit Screens under Headset Output Stereo 3D & Screens now lists Edit Screens and its snaps right under the switch that reveals them, then the headset's own setup, then where the screens go, with the per-screen rows last and Visible first among them. * openxr: track each held screen's hinge on the frame loop The frame loop already re-snaps each held screen every frame. It now also keeps, per hand, the hinge that snap holds whole, until the edge leaves the hinge's 4.5 cm reach, where the frame draws it, so edit mode can mark it. A kept hinge whose target no longer matches is dropped. video_xr gains the hinge line's ends, along the overlap of the two real edges and midway across the gap, an outline cut that drops one edge's rim, and a green strip in the laser's image, before the tags. * openxr: mark a hinged headset screen with a green line While a held screen's hinge holds, the two edges that meet drop their outline rim and a 6 mm green line runs along the hinge where they overlap, midway across the gap, so it is clear when the hinge has taken hold. The line is drawn as the beam is, a centimetre nearer the eye than the edges, since SteamVR does not keep the order of overlapping quad layers, and comes after the outlines in the layer budget; hidden rims cost no layer. * input: buzz longer as a headset screen hinges A hinge taking hold now gets one 150 ms buzz at 0.8 on the hand carrying the screen, against the 20 ms snap tick, so the attach can be felt. It fires again only after the edge leaves the hinge's reach, hinges elsewhere, or the other hand takes the screen it hinges on, so a swing past square and back does not repeat it. Ticks due while it plays are skipped rather than cutting it short. * openxr: find headset screens resting in a hinge Two screens no hand holds rest in a hinge when their poses pass the test that engages a carried screen's hinge, with either one carried, and the hinge, held whole with nothing else pulling, leaves the carried one where it is. So a hinge found at rest stays hinged when its screen is taken. The engaged test moves into its own function so both use the same one, and one target can pull whole whatever the grab's fade. * openxr: keep a headset screen's hinge shown at rest In Edit Screens, two screens no hand holds that rest in a hinge keep the green line and their hidden rims, whether let go hinged or loaded that way. The main thread counts them only when a resting screen changes and sends them with the hands' record, so a release and its resting pair arrive together; the frame loop places each line from the screens it shows. A screen hinged at rest on two adjacent edges still keeps one of those rims. The hands' record now outgrows the quads, so the seqlock's copy is sized to the larger of the two. * openxr: pick up a hinged headset screen still hinged Taking up a screen that rests in a hinge starts the carry on that hinge, whole from the first poll, with no buzz and no jump, until it leaves the hinge's reach, another hinge takes hold, or the other hand takes the screen it hinges on. Until the grab's own snapping has faded in, the kept hinge's target still pulls whole, so a straight pull out does not hop. The grab carries the hinge so both threads hold it the same; of several, the one the snap ranks best carries over, and only where holding it moves nothing. While the other screens fade in, the hinge's screen also leads the turn, so a nearer one still fading does not take it. * openxr: end a headset screen's hinge where a push passes the stop Pushing a hinged screen into its neighbour holds the edge at touching for 3 cm of push, fading out by 5.5 cm. Where it stops holding, the hinge ends: the line goes, the rims come back, and the lid and buzz are cleared, so screens pushed into each other show no hinge that a let-go there would not rest in. Pulled back, the hinge takes hold again 5 mm short of where it ended, with the long buzz, so a tremor there does not flicker it. The grab carries that through flag, and the frame loop keeps its line until the main thread sets it, so the two threads never disagree for more than a poll. At Hinge Gap 1 a pair let go touching rests hinged and is taken up hinged, as at every other gap. A screen swung into a square corner gets the long buzz on arrival, and the other hand taking the target does not hop the carried screen by the push's depth. * input: let go of a headset screen where it was before the grip opened Opening the grip twitches the hand, and the poll that sees the grip open would move the screen by that twitched aim. Half a degree of pitch moves a screen 1.8 m out by 1.6 cm, enough to knock it off its hinge's gap or out of level, so it would not rest hinged. Each hand keeps a short trail of where, turned and as large as its screen showed, entries at least 10 ms apart, and a grip let go puts the screen as it showed 80 ms before (INPUT_OPENXR_EDIT_REWIND_US), or as it was taken if held for less. Edit mode's end and a recenter let go where the screen shows. * openxr: find where a let-go headset screen settles in its hinge A screen let go while its hinge shows should land exactly in that hinge, so the hinge still shows at rest and a pick-up is hinged. video_xr_hinge_settle holds the hinge whole from the hand's pose, then moves the edge to the set gap from within 3 cm of it (touching stays where the stop holds it) and levels it along the edge within the level pull's reach. Its result must pass the rest test, and it turns no further than a grab's hinge engages, which shares that test. A pair resting inside a settle band but off its point is no longer listed at rest, since a pick-up and let-go would move it. A touching rest is taken 5 mm deeper into the push stop, at every Hinge Gap, so a hand that drifts less than that apart before letting go settles touching rather than at the gap. * openxr: settle a let-go headset screen into its hinge A screen let go while its hinge shows now goes exactly into that hinge: to the set gap from within 3 cm of it, touching from the stop's hold, and level along the edge from within the level pull's reach. It then rests there, listed and green, in the same publish, and is saved there. Elsewhere it stays where it shows, as before. Each trail entry also records where the hand put the screen with no snap and whether a let-go there settles. At the let-go the rewound entry is settled again against the screens as they are now, at that entry's size, and put in one go. * openxr: let a hinged headset screen rest at any fold Snap to Screens' turn to flat, and its turn to square at a corner, is whole within 5 degrees and fades out by 10, so a hinged screen held there shows at twice its angle off less 10. No fold shown in that fade read as a rest: the pair was not listed, a let-go there did not settle into its hinge, and taking it up would have moved it. Where a hand takes a rest, it now holds the screen at the angle the turn's fade shows it from, the inverse of the turn's pull, so every fold rests, is listed and is taken up unmoved. Held snapping is unchanged. * input: keep a headset screen's hinge through a shaking hand Edit Screens' hinge buzz, lid and push stop followed the snap's own engage and reach on every poll. A hand shaking half a degree (1.6 cm at the screen) about a hinge's edge flipped them many times a second, each flip a long buzz. Each hold now keeps one mark: the hinge a let-go would settle into. It takes hold at once, with the long buzz, and lets go only once polls have seen the hand out of where a let-go would settle for 150 ms, each poll counting at most 50 ms, so a stalled main thread or a spell untracked never lets it go alone. The other hand taking its target, hinged elsewhere or not, the target leaving and the let-go end it at once. The lid waits for the mark to go, the push stop follows it, and a let-go while it shows settles into it from where the hand last would have, edit mode's end and a recenter included. * openxr: draw a held screen's hinge as the main thread marks it The grab carries the main thread's hinge mark, and the frame loop draws a held screen's green line and cuts its rims from that mark alone, through video_xr_grab_marked, while it snaps the screen every frame. A frame loop taking the hinge by itself between polls would flicker the line for a hand shaking at the edge of the hinge's range while the mark held. A mark whose target the frame does not show cuts no rim. The other hand taking the mark's target ends it, and the lid, on any poll, tracked or not, so a lost hand's line does not come back when that hand lets go. video_xr_grab_near_hinge loses its past argument, which only the frame loop's keep used. * openxr: keep edit mode's hinge layers in place SteamVR does not keep submission order for overlapping quad layers, so a layer added, dropped or moved to another index can pop the edit outlines in front of the screens, as a wobble at a hinge would do to its line's layer. The hinge lines are fixed slots: one for each hand holding a screen, hand 0 first, then one for each pair at rest. A slot with no line to show is drawn in place from its screen's middle, at rows of the laser image that are empty either way up. The layer count and every index change only at a grab, a let-go or a re-count of the pairs at rest; a mark only changes crops and which rows a slot shows. * input: date a let-go's trail by frame and stop it at a stall Each trail entry is dated by the frame its aims are from, one a frame and per hand, and the release poll records a new frame's aims first. The rewind stops at a stall, entries more than 2.5 frames apart, a frame counted as at least 20 ms so a fast headset's close entries never read as one. Under load a stall of 0.1 to 0.3 s can come just before the release; the entry from 80 ms back would then hold the pose from before it and step the let-go back across all the stall's motion. With Edit Smoothing on, which damps the twitch, a let-go that does not settle into a hinge stays where and as large as it shows: a rewind there would step back by what the smoothed aim still lags. The hinge decision and the settle use the trail either way. * openxr: cut edit outlines from cells instead of turning them Cutting a top or bottom rim from the one outline image turns both outline quads a quarter turn and swaps their width and height, and on SteamVR that can blink every edit outline as the hinge takes hold or lets go; side cuts, which never turn, do not. The laser's image carries twelve pre-cut outline cells after the tags, faint and bright, for a cut top, bottom, left, right, top and bottom, or left and right, so a cut only picks a cell and the quads keep their pose and size. The image is then 5582 texels wide. A runtime whose swapchains are narrower, or that does not say how wide they can be, keeps the turned and cropped outline at 2498 or 1208 wide. One log line at the laser's creation gives the width chosen and the runtime's limit. GL writes the top and bottom cells swapped for its bottom-up rows, and Android's copy of the image is allocated rather than static. The edit-hinge-3ds-narrow e2e case runs the turned cut at RA_XR_LAYER_MAX_WIDTH=4096, on Vulkan and the GL EGL lanes. * video: draw headset screens straight into the runtime's images Each headset screen was drawn into an image of the driver's own and copied from it into the runtime's on every new frame, Vulkan with a render pass and GL3 with a blit. Screens are now drawn into the runtime's image itself, as before per-screen placement, with no image of the driver's and no copy. A screen drawn again with no new frame - resized, made again or moved while paused - replays the last frame's final pass from the chain: build_viewport_pass_replay draws it at the new size from what it read then, the passes' outputs, their feedback and the history that frame saw, with that frame's count. Nothing else runs, feedback does not swap and history stays, so a feedback or history preset holds still while paused. A chain made to replay keeps one more history image, so the frame's end writes where the last frame did not read; the window's chains keep what they did. This also has movie frames reach the headset, which the copy held at the first one, and draws a screen resized while paused at its new size rather than stretching the old image. * openxr: leave what users who never edit see as it was Screens seen from behind turn to their grey backs only while Edit Screens is on, where screens are turned around; outside it nothing changes and no head is located for them. The grabs carry whether editing is on. The menu opens at its own spot, straight ahead of the anchor, as it did. Menu in Front of Screen 1, off by default, keeps it just in front of screen 1 and moving with it. The frame loop copies the main thread's grabs only once their stamp moves, so outside edit mode no frame copies them. A new session clears the frame loop's own copy and passes over what was published before it, rather than publishing itself: the main thread stays the grabs' one writer. On Touch, the left menu button that opens the menu from edit mode is spent until let go: held on as edit mode ends, it is no Start and does not toggle the menu again after a second. --------- Co-authored-by: libretroadmin <[email protected]>
875 lines
33 KiB
C
875 lines
33 KiB
C
/* RetroArch - A frontend for libretro.
|
|
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
|
* Copyright (C) 2011-2017 - Daniel De Matteis
|
|
* Copyright (C) 2016-2019 - Brad Parker
|
|
*
|
|
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
|
* of the GNU General Public License as published by the Free Software Found-
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
|
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with RetroArch.
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef __MENU_DRIVER_H__
|
|
#define __MENU_DRIVER_H__
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
|
|
#include <boolean.h>
|
|
#include <retro_common_api.h>
|
|
#include <formats/image.h>
|
|
#include <queues/task_queue.h>
|
|
#include <retro_miscellaneous.h>
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "../config.h"
|
|
#endif
|
|
|
|
#include "menu_defines.h"
|
|
#include "menu_input.h"
|
|
#include "../input/input_osk.h"
|
|
#include "menu_entries.h"
|
|
#include "menu_shader.h"
|
|
#include "../gfx/gfx_animation.h"
|
|
#include "../gfx/gfx_display.h"
|
|
#include "../gfx/gfx_thumbnail.h"
|
|
#include "../gfx/font_driver.h"
|
|
#include "../performance_counters.h"
|
|
|
|
|
|
RETRO_BEGIN_DECLS
|
|
|
|
#ifndef MAX_COUNTERS
|
|
#define MAX_COUNTERS 64
|
|
#endif
|
|
|
|
#ifndef MAX_CHEAT_COUNTERS
|
|
#define MAX_CHEAT_COUNTERS 6000
|
|
#endif
|
|
|
|
#define SCROLL_INDEX_SIZE (2 * (26 + 2) + 1)
|
|
|
|
#ifdef __EMSCRIPTEN__
|
|
/* This task reads a variable that is set asynchronously, so the first check might fail.
|
|
* Check more often because it is cheap and to avoid a long period of missing power info. */
|
|
#define POWERSTATE_CHECK_INTERVAL 1000000
|
|
#else
|
|
#define POWERSTATE_CHECK_INTERVAL (30 * 1000000)
|
|
#endif
|
|
|
|
#define DATETIME_CHECK_INTERVAL 1000000
|
|
/* Single-click playlist button hold: entry drawing stays
|
|
* suppressed for this long (us) after the click */
|
|
#define MENU_DRAW_ENTRY_DELAY 500000
|
|
|
|
#define MENU_LIST_GET(list, idx) ((list) ? ((list)->menu_stack[(idx)]) : NULL)
|
|
|
|
#define MENU_LIST_GET_SELECTION(list, idx) ((list) ? ((list)->selection_buf[(idx)]) : NULL)
|
|
|
|
#define MENU_LIST_GET_STACK_SIZE(list, idx) ((list)->menu_stack[(idx)]->size)
|
|
|
|
#define MENU_ENTRIES_GET_SELECTION_BUF_PTR_INTERNAL(menu_st, idx) ((menu_st->entries.list) ? MENU_LIST_GET_SELECTION(menu_st->entries.list, (unsigned)idx) : NULL)
|
|
#define MENU_ENTRIES_NEEDS_REFRESH(menu_st) (!((menu_st->flags & MENU_ST_FLAG_ENTRIES_NONBLOCKING_REFRESH) || !(menu_st->flags & MENU_ST_FLAG_ENTRIES_NEED_REFRESH)))
|
|
|
|
#define MENU_SETTINGS_CORE_INFO_NONE 0xffff
|
|
#define MENU_SETTINGS_CORE_OPTION_NONE 0xffff
|
|
#define MENU_SETTINGS_CHEEVOS_NONE 0xffff
|
|
#define MENU_SETTINGS_CORE_OPTION_START 0x10000
|
|
#define MENU_SETTINGS_CHEEVOS_START 0x40000
|
|
#define MENU_SETTINGS_NETPLAY_ROOMS_START 0x80000
|
|
|
|
/* "Normalize" non-alphabetical entries so they
|
|
* are lumped together for purposes of jumping. */
|
|
#define ELEM_GET_FIRST_CHAR(ret) ((ret < 'a') ? ('a' - 1) : (ret > 'z') ? ('z' + 1) : ret)
|
|
|
|
enum menu_settings_type
|
|
{
|
|
MENU_SETTINGS_NONE = FILE_TYPE_LAST + 1,
|
|
MENU_SETTINGS,
|
|
MENU_SETTINGS_TAB,
|
|
MENU_HISTORY_TAB,
|
|
MENU_FAVORITES_TAB,
|
|
MENU_MUSIC_TAB,
|
|
MENU_VIDEO_TAB,
|
|
MENU_IMAGES_TAB,
|
|
MENU_NETPLAY_TAB,
|
|
MENU_EXPLORE_TAB,
|
|
MENU_CONTENTLESS_CORES_TAB,
|
|
MENU_ADD_TAB,
|
|
MENU_PLAYLISTS_TAB,
|
|
MENU_SETTING_DROPDOWN_ITEM,
|
|
MENU_SETTING_DROPDOWN_ITEM_RESOLUTION,
|
|
MENU_SETTING_DROPDOWN_ITEM_CRT_SUPER_RESOLUTION,
|
|
MENU_SETTING_DROPDOWN_ITEM_HEADSET_REFRESH_RATE,
|
|
MENU_SETTING_DROPDOWN_ITEM_VIDEO_SHADER_PARAM,
|
|
MENU_SETTING_DROPDOWN_ITEM_VIDEO_SHADER_PRESET_PARAM,
|
|
MENU_SETTING_DROPDOWN_ITEM_VIDEO_SHADER_NUM_PASS,
|
|
MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_DEFAULT_CORE,
|
|
MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_LABEL_DISPLAY_MODE,
|
|
MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_RIGHT_THUMBNAIL_MODE,
|
|
MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_LEFT_THUMBNAIL_MODE,
|
|
MENU_SETTING_DROPDOWN_ITEM_PLAYLIST_SORT_MODE,
|
|
MENU_SETTING_DROPDOWN_ITEM_SCAN_METHOD,
|
|
MENU_SETTING_DROPDOWN_ITEM_SCAN_USE_DB,
|
|
MENU_SETTING_DROPDOWN_ITEM_SCAN_DB_SELECT,
|
|
MENU_SETTING_DROPDOWN_ITEM_MANUAL_CONTENT_SCAN_SYSTEM_NAME,
|
|
MENU_SETTING_DROPDOWN_ITEM_MANUAL_CONTENT_SCAN_CORE_NAME,
|
|
MENU_SETTING_DROPDOWN_ITEM_DISK_INDEX,
|
|
MENU_SETTING_DROPDOWN_ITEM_INPUT_RETROPAD_BIND,
|
|
MENU_SETTING_DROPDOWN_ITEM_INPUT_DEVICE_TYPE,
|
|
MENU_SETTING_DROPDOWN_ITEM_INPUT_DEVICE_INDEX,
|
|
MENU_SETTING_DROPDOWN_ITEM_INPUT_SELECT_RESERVED_DEVICE,
|
|
#ifdef ANDROID
|
|
MENU_SETTING_DROPDOWN_ITEM_INPUT_SELECT_PHYSICAL_KEYBOARD,
|
|
#endif
|
|
MENU_SETTING_DROPDOWN_ITEM_INPUT_DESCRIPTION,
|
|
MENU_SETTING_DROPDOWN_ITEM_INPUT_DESCRIPTION_KBD,
|
|
MENU_SETTING_DROPDOWN_ITEM_AUDIO_DEVICE,
|
|
#ifdef HAVE_MICROPHONE
|
|
MENU_SETTING_DROPDOWN_ITEM_MICROPHONE_DEVICE,
|
|
#endif
|
|
#ifdef HAVE_NETWORKING
|
|
MENU_SETTING_DROPDOWN_ITEM_NETPLAY_MITM_SERVER,
|
|
#endif
|
|
MENU_SETTING_DROPDOWN_SETTING_CORE_OPTIONS_ITEM,
|
|
MENU_SETTING_DROPDOWN_SETTING_STRING_OPTIONS_ITEM,
|
|
MENU_SETTING_DROPDOWN_SETTING_FLOAT_ITEM,
|
|
MENU_SETTING_DROPDOWN_SETTING_INT_ITEM,
|
|
MENU_SETTING_DROPDOWN_SETTING_UINT_ITEM,
|
|
MENU_SETTING_DROPDOWN_SETTING_CORE_OPTIONS_ITEM_SPECIAL,
|
|
MENU_SETTING_DROPDOWN_SETTING_STRING_OPTIONS_ITEM_SPECIAL,
|
|
MENU_SETTING_DROPDOWN_SETTING_FLOAT_ITEM_SPECIAL,
|
|
MENU_SETTING_DROPDOWN_SETTING_INT_ITEM_SPECIAL,
|
|
MENU_SETTING_DROPDOWN_SETTING_UINT_ITEM_SPECIAL,
|
|
MENU_SETTING_NO_ITEM,
|
|
MENU_SETTING_DRIVER,
|
|
MENU_SETTING_ACTION,
|
|
MENU_SETTING_ACTION_RUN,
|
|
MENU_SETTING_ACTION_CLOSE,
|
|
MENU_SETTING_ACTION_CLOSE_HORIZONTAL,
|
|
MENU_SETTING_ACTION_CORE_OPTIONS,
|
|
MENU_SETTING_ACTION_CORE_OPTION_OVERRIDE_LIST,
|
|
MENU_SETTING_ACTION_CORE_INPUT_REMAPPING_OPTIONS,
|
|
MENU_SETTING_ACTION_REMAP_FILE_MANAGER_LIST,
|
|
MENU_SETTING_ACTION_CORE_CHEAT_OPTIONS,
|
|
MENU_SETTING_ACTION_CORE_MANAGER_OPTIONS,
|
|
#ifdef HAVE_MIST
|
|
MENU_SETTING_ACTION_CORE_MANAGER_STEAM_OPTIONS,
|
|
MENU_SETTING_ACTION_CORE_STEAM_INSTALL,
|
|
MENU_SETTING_ACTION_CORE_STEAM_UNINSTALL,
|
|
#endif
|
|
MENU_SETTING_ACTION_CORE_DISK_OPTIONS,
|
|
MENU_SETTING_ACTION_CORE_SHADER_OPTIONS,
|
|
MENU_SETTING_ACTION_SAVESTATE,
|
|
MENU_SETTING_ACTION_LOADSTATE,
|
|
MENU_SETTING_ACTION_PLAYREPLAY,
|
|
MENU_SETTING_ACTION_RECORDREPLAY,
|
|
MENU_SETTING_ACTION_HALTREPLAY,
|
|
MENU_SETTING_ACTION_SCREENSHOT,
|
|
MENU_SETTING_ACTION_DELETE_ENTRY,
|
|
MENU_SETTING_ACTION_RESET,
|
|
MENU_SETTING_ACTION_CORE_LOCK,
|
|
MENU_SETTING_ACTION_CORE_SET_STANDALONE_EXEMPT,
|
|
MENU_SETTING_ACTION_CORE_DELETE,
|
|
MENU_SETTING_ACTION_FAVORITES_DIR, /* "Start Directory" */
|
|
MENU_SETTING_STRING_OPTIONS,
|
|
MENU_SETTING_GROUP,
|
|
MENU_SETTING_SUBGROUP,
|
|
MENU_SETTING_HORIZONTAL_MENU,
|
|
MENU_SETTING_ACTION_PAUSE_ACHIEVEMENTS,
|
|
MENU_SETTING_ACTION_RESUME_ACHIEVEMENTS,
|
|
MENU_INFO_ACHIEVEMENTS_SERVER_UNREACHABLE,
|
|
MENU_SETTING_PLAYLIST_MANAGER_DEFAULT_CORE,
|
|
MENU_SETTING_PLAYLIST_MANAGER_LABEL_DISPLAY_MODE,
|
|
MENU_SETTING_PLAYLIST_MANAGER_RIGHT_THUMBNAIL_MODE,
|
|
MENU_SETTING_PLAYLIST_MANAGER_LEFT_THUMBNAIL_MODE,
|
|
MENU_SETTING_PLAYLIST_MANAGER_SORT_MODE,
|
|
MENU_BLUETOOTH,
|
|
MENU_WIFI,
|
|
MENU_WIFI_DISCONNECT,
|
|
MENU_ROOM,
|
|
MENU_ROOM_LAN,
|
|
MENU_ROOM_RELAY,
|
|
MENU_NETPLAY_LAN_SCAN,
|
|
MENU_NETPLAY_KICK,
|
|
MENU_NETPLAY_BAN,
|
|
MENU_INFO_MESSAGE,
|
|
MENU_SETTINGS_SHADER_PARAMETER_0,
|
|
MENU_SETTINGS_SHADER_PARAMETER_LAST = MENU_SETTINGS_SHADER_PARAMETER_0 + (GFX_MAX_PARAMETERS - 1),
|
|
MENU_SETTINGS_SHADER_PRESET_PARAMETER_0,
|
|
MENU_SETTINGS_SHADER_PRESET_PARAMETER_LAST = MENU_SETTINGS_SHADER_PRESET_PARAMETER_0 + (GFX_MAX_PARAMETERS - 1),
|
|
MENU_SETTINGS_SHADER_PASS_0,
|
|
MENU_SETTINGS_SHADER_PASS_LAST = MENU_SETTINGS_SHADER_PASS_0 + (GFX_MAX_SHADERS - 1),
|
|
MENU_SETTINGS_SHADER_PASS_FILTER_0,
|
|
MENU_SETTINGS_SHADER_PASS_FILTER_LAST = MENU_SETTINGS_SHADER_PASS_FILTER_0 + (GFX_MAX_SHADERS - 1),
|
|
MENU_SETTINGS_SHADER_PASS_SCALE_0,
|
|
MENU_SETTINGS_SHADER_PASS_SCALE_LAST = MENU_SETTINGS_SHADER_PASS_SCALE_0 + (GFX_MAX_SHADERS - 1),
|
|
|
|
MENU_SETTINGS_CORE_DISK_OPTIONS_DISK_INDEX,
|
|
MENU_SETTINGS_CORE_DISK_OPTIONS_DISK_IMAGE_APPEND,
|
|
MENU_SETTINGS_CORE_DISK_OPTIONS_DISK_CYCLE_TRAY_STATUS,
|
|
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_BEGIN,
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_BEGIN + MENU_SETTINGS_AUDIO_MIXER_MAX_STREAMS,
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_BEGIN,
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_BEGIN + MENU_SETTINGS_AUDIO_MIXER_MAX_STREAMS,
|
|
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_STOP_BEGIN,
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_STOP_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_STOP_BEGIN + MENU_SETTINGS_AUDIO_MIXER_MAX_STREAMS,
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_REMOVE_BEGIN,
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_REMOVE_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_REMOVE_BEGIN + MENU_SETTINGS_AUDIO_MIXER_MAX_STREAMS,
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_BEGIN,
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_BEGIN + MENU_SETTINGS_AUDIO_MIXER_MAX_STREAMS,
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_BEGIN,
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_BEGIN + MENU_SETTINGS_AUDIO_MIXER_MAX_STREAMS,
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_SEQUENTIAL_BEGIN,
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_SEQUENTIAL_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_SEQUENTIAL_BEGIN + MENU_SETTINGS_AUDIO_MIXER_MAX_STREAMS,
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN,
|
|
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN + MENU_SETTINGS_AUDIO_MIXER_MAX_STREAMS,
|
|
MENU_SETTINGS_BIND_BEGIN,
|
|
MENU_SETTINGS_BIND_LAST = MENU_SETTINGS_BIND_BEGIN + RARCH_ANALOG_RIGHT_Y_MINUS,
|
|
MENU_SETTINGS_BIND_ALL_LAST = MENU_SETTINGS_BIND_BEGIN + RARCH_MENU_TOGGLE,
|
|
|
|
MENU_SETTINGS_CUSTOM_BIND,
|
|
MENU_SETTINGS_CUSTOM_BIND_KEYBOARD,
|
|
MENU_SETTINGS_CUSTOM_BIND_ALL,
|
|
MENU_SETTINGS_CUSTOM_BIND_DEFAULT_ALL,
|
|
MENU_SETTINGS_LIBRETRO_PERF_COUNTERS_BEGIN,
|
|
MENU_SETTINGS_LIBRETRO_PERF_COUNTERS_END = MENU_SETTINGS_LIBRETRO_PERF_COUNTERS_BEGIN + (MAX_COUNTERS - 1),
|
|
MENU_SETTINGS_PERF_COUNTERS_BEGIN,
|
|
MENU_SETTINGS_PERF_COUNTERS_END = MENU_SETTINGS_PERF_COUNTERS_BEGIN + (MAX_COUNTERS - 1),
|
|
MENU_SETTINGS_CHEAT_BEGIN,
|
|
MENU_SETTINGS_CHEAT_END = MENU_SETTINGS_CHEAT_BEGIN + (MAX_CHEAT_COUNTERS - 1),
|
|
|
|
MENU_SETTINGS_INPUT_LIBRETRO_DEVICE,
|
|
MENU_SETTINGS_INPUT_ANALOG_DPAD_MODE,
|
|
MENU_SETTINGS_INPUT_INPUT_REMAP_PORT,
|
|
MENU_SETTINGS_INPUT_BEGIN,
|
|
MENU_SETTINGS_INPUT_END = MENU_SETTINGS_INPUT_BEGIN + RARCH_CUSTOM_BIND_LIST_END + 7,
|
|
MENU_SETTINGS_INPUT_DESC_BEGIN,
|
|
MENU_SETTINGS_INPUT_DESC_END = MENU_SETTINGS_INPUT_DESC_BEGIN + (RARCH_ANALOG_BIND_LIST_END * MAX_USERS),
|
|
MENU_SETTINGS_INPUT_DESC_KBD_BEGIN,
|
|
MENU_SETTINGS_INPUT_DESC_KBD_END = MENU_SETTINGS_INPUT_DESC_KBD_BEGIN + (RARCH_MAX_KEYS * MAX_USERS),
|
|
MENU_SETTINGS_REMAPPING_PORT_BEGIN,
|
|
MENU_SETTINGS_REMAPPING_PORT_END = MENU_SETTINGS_REMAPPING_PORT_BEGIN + (MAX_USERS),
|
|
|
|
MENU_SETTINGS_SUBSYSTEM_LOAD,
|
|
MENU_SETTINGS_SUBSYSTEM_ADD,
|
|
MENU_SETTINGS_SUBSYSTEM_LAST = MENU_SETTINGS_SUBSYSTEM_ADD + RARCH_MAX_SUBSYSTEMS,
|
|
MENU_SETTINGS_CHEAT_MATCH,
|
|
|
|
MENU_SET_SCREEN_BRIGHTNESS,
|
|
|
|
#if defined(HAVE_LIBNX)
|
|
MENU_SET_SWITCH_CPU_PROFILE,
|
|
#endif
|
|
|
|
MENU_SETTINGS_CPU_POLICY_SET_MINFREQ,
|
|
MENU_SETTINGS_CPU_POLICY_SET_MAXFREQ,
|
|
MENU_SETTINGS_CPU_POLICY_SET_GOVERNOR,
|
|
MENU_SETTINGS_CPU_MANAGED_SET_MINFREQ,
|
|
MENU_SETTINGS_CPU_MANAGED_SET_MAXFREQ,
|
|
|
|
MENU_SET_CDROM_LIST,
|
|
MENU_SET_LOAD_CDROM_LIST,
|
|
MENU_SET_EJECT_DISC,
|
|
MENU_SET_CDROM_INFO,
|
|
MENU_SETTING_ACTION_DELETE_PLAYLIST,
|
|
MENU_SETTING_ACTION_PLAYLIST_MANAGER_RESET_CORES,
|
|
MENU_SETTING_ACTION_PLAYLIST_MANAGER_CLEAN_PLAYLIST,
|
|
MENU_SETTING_ACTION_PLAYLIST_MANAGER_REFRESH_PLAYLIST,
|
|
|
|
MENU_SETTING_SCAN_METHOD,
|
|
MENU_SETTING_SCAN_USE_DB,
|
|
MENU_SETTING_SCAN_DB_SELECT,
|
|
MENU_SETTING_MANUAL_CONTENT_SCAN_DIR,
|
|
MENU_SETTING_MANUAL_CONTENT_SCAN_SYSTEM_NAME,
|
|
MENU_SETTING_MANUAL_CONTENT_SCAN_CORE_NAME,
|
|
MENU_SETTING_ACTION_MANUAL_CONTENT_SCAN_START,
|
|
|
|
MENU_SETTING_ACTION_CORE_CREATE_BACKUP,
|
|
MENU_SETTING_ACTION_CORE_RESTORE_BACKUP,
|
|
MENU_SETTING_ITEM_CORE_RESTORE_BACKUP,
|
|
MENU_SETTING_ACTION_CORE_DELETE_BACKUP,
|
|
MENU_SETTING_ITEM_CORE_DELETE_BACKUP,
|
|
|
|
MENU_SETTING_ACTION_VIDEO_FILTER_REMOVE,
|
|
MENU_SETTING_ACTION_AUDIO_DSP_PLUGIN_REMOVE,
|
|
|
|
MENU_SETTING_ACTION_GAME_SPECIFIC_CORE_OPTIONS_CREATE,
|
|
MENU_SETTING_ACTION_GAME_SPECIFIC_CORE_OPTIONS_REMOVE,
|
|
MENU_SETTING_ACTION_FOLDER_SPECIFIC_CORE_OPTIONS_CREATE,
|
|
MENU_SETTING_ACTION_FOLDER_SPECIFIC_CORE_OPTIONS_REMOVE,
|
|
MENU_SETTING_ACTION_CORE_OPTIONS_RESET,
|
|
MENU_SETTING_ACTION_CORE_OPTIONS_FLUSH,
|
|
|
|
MENU_SETTING_ACTION_REMAP_FILE_LOAD,
|
|
MENU_SETTING_ACTION_REMAP_FILE_SAVE_AS,
|
|
MENU_SETTING_ACTION_REMAP_FILE_SAVE_CORE,
|
|
MENU_SETTING_ACTION_REMAP_FILE_SAVE_CONTENT_DIR,
|
|
MENU_SETTING_ACTION_REMAP_FILE_SAVE_GAME,
|
|
MENU_SETTING_ACTION_REMAP_FILE_REMOVE_CORE,
|
|
MENU_SETTING_ACTION_REMAP_FILE_REMOVE_CONTENT_DIR,
|
|
MENU_SETTING_ACTION_REMAP_FILE_REMOVE_GAME,
|
|
MENU_SETTING_ACTION_REMAP_FILE_RESET,
|
|
MENU_SETTING_ACTION_REMAP_FILE_FLUSH,
|
|
|
|
MENU_SETTING_ACTION_CONTENTLESS_CORE_RUN,
|
|
MENU_SETTING_ACTION_STATE_SLOT_RUN,
|
|
|
|
MENU_SETTINGS_LAST
|
|
};
|
|
|
|
struct menu_list
|
|
{
|
|
file_list_t **menu_stack;
|
|
size_t menu_stack_size;
|
|
file_list_t **selection_buf;
|
|
size_t selection_buf_size;
|
|
};
|
|
|
|
typedef struct menu_list menu_list_t;
|
|
|
|
typedef struct menu_ctx_load_image
|
|
{
|
|
void *data;
|
|
enum menu_image_type type;
|
|
} menu_ctx_load_image_t;
|
|
|
|
typedef struct menu_ctx_driver
|
|
{
|
|
/* Set a framebuffer texture. This is used for instance by RGUI. */
|
|
void (*set_texture)(void *data);
|
|
/* Render a messagebox to the screen. */
|
|
void (*render_messagebox)(void *data, const char *msg);
|
|
void (*render)(void *data, unsigned dims, bool is_idle);
|
|
void (*frame)(void *data, video_frame_info_t *video_info);
|
|
/* Initializes the menu driver. (setup) */
|
|
void* (*init)(void**, bool);
|
|
/* Frees the menu driver. (teardown) */
|
|
void (*free)(void*);
|
|
/* This will be invoked when we are running a hardware context
|
|
* and we have just flushed the state. For instance - we have
|
|
* just toggled fullscreen, the GL driver did a teardown/setup -
|
|
* we now need to rebuild all of our textures and state for the
|
|
* menu driver. */
|
|
void (*context_reset)(void *data, bool video_is_threaded);
|
|
/* This will be invoked when we are running a hardware context
|
|
* and the context in question wants to tear itself down. All
|
|
* textures and related state on the menu driver will also
|
|
* be freed up then. */
|
|
void (*context_destroy)(void *data);
|
|
void (*populate_entries)(void *data,
|
|
const char *path, const char *label,
|
|
unsigned k);
|
|
void (*toggle)(void *userdata, bool);
|
|
/* This will clear the navigation position. */
|
|
void (*navigation_clear)(void *, bool);
|
|
/* This will decrement the navigation position by one. */
|
|
void (*navigation_decrement)(void *data);
|
|
/* This will increment the navigation position by one. */
|
|
void (*navigation_increment)(void *data);
|
|
void (*navigation_set)(void *data, bool);
|
|
void (*navigation_set_last)(void *data);
|
|
/* This will descend the navigation position by one alphabet letter. */
|
|
void (*navigation_descend_alphabet)(void *, size_t *);
|
|
/* This will ascend the navigation position by one alphabet letter. */
|
|
void (*navigation_ascend_alphabet)(void *, size_t *);
|
|
/* Initializes a new menu list. */
|
|
bool (*lists_init)(void*);
|
|
void (*list_insert)(void *userdata,
|
|
file_list_t *list, const char *, const char *, const char *, size_t,
|
|
unsigned);
|
|
int (*list_prepend)(void *userdata,
|
|
file_list_t *list, const char *, const char *, size_t);
|
|
void (*list_free)(file_list_t *list, size_t, size_t);
|
|
void (*list_clear)(file_list_t *list);
|
|
void (*list_cache)(void *data, enum menu_list_type, unsigned);
|
|
int (*list_push)(void *data, void *userdata, menu_displaylist_info_t*, unsigned);
|
|
size_t(*list_get_selection)(void *data);
|
|
size_t(*list_get_size)(void *data, enum menu_list_type type);
|
|
void *(*list_get_entry)(void *data, enum menu_list_type type, unsigned i);
|
|
void (*list_set_selection)(void *data, file_list_t *list);
|
|
int (*bind_init)(menu_file_list_cbs_t *cbs,
|
|
const char *path, const char *label, unsigned type, size_t idx);
|
|
/* Load an image for use by the menu driver */
|
|
bool (*load_image)(void *userdata, void *data, enum menu_image_type type);
|
|
const char *ident;
|
|
int (*environ_cb)(enum menu_environ_cb type, void *data, void *userdata);
|
|
void (*update_thumbnail_path)(void *data, unsigned i, char pos);
|
|
void (*update_thumbnail_image)(void *data);
|
|
void (*refresh_thumbnail_image)(void *data, size_t i);
|
|
void (*set_thumbnail_content)(void *data, const char *s);
|
|
int (*osk_ptr_at_pos)(void *data, int x, int y, unsigned dims);
|
|
bool (*osk_pointer_over_textbox)(void *data, int x, int y, unsigned dims);
|
|
void (*update_savestate_thumbnail_path)(void *data, unsigned i);
|
|
void (*update_savestate_thumbnail_image)(void *data);
|
|
int (*pointer_down)(void *data, unsigned x, unsigned y, unsigned ptr,
|
|
menu_file_list_cbs_t *cbs,
|
|
menu_entry_t *entry, unsigned action);
|
|
int (*pointer_up)(void *data, unsigned x, unsigned y, unsigned ptr,
|
|
enum menu_input_pointer_gesture gesture,
|
|
menu_file_list_cbs_t *cbs,
|
|
menu_entry_t *entry, unsigned action);
|
|
/* This will be invoked whenever a menu entry action
|
|
* (menu_entry_action()) is performed */
|
|
int (*entry_action)(void *userdata, menu_entry_t *entry, size_t i, enum menu_action action);
|
|
/* Move the list itself by the given number of mouse wheel
|
|
* notches, negative towards the top, leaving the selection
|
|
* where it is. Drivers whose list position *is* the selection
|
|
* leave this NULL and keep getting MENU_ACTION_UP/DOWN.
|
|
* Returns false when the driver cannot scroll right now. */
|
|
bool (*wheel_scroll)(void *userdata, int notches);
|
|
} menu_ctx_driver_t;
|
|
|
|
typedef struct
|
|
{
|
|
uint64_t state;
|
|
|
|
const menu_ctx_driver_t *driver_ctx;
|
|
void *userdata;
|
|
|
|
char *core_buf;
|
|
size_t core_len;
|
|
|
|
/* This is used for storing intermediary variables
|
|
* that get used later on during menu actions -
|
|
* for instance, selecting a shader pass for a shader
|
|
* slot */
|
|
struct
|
|
{
|
|
unsigned unsigned_var;
|
|
} scratchpad;
|
|
unsigned rpl_entry_selection_ptr;
|
|
int16_t state_slot_run;
|
|
|
|
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
|
|
/* Used to cache the type and directory
|
|
* of the last shader preset/pass loaded
|
|
* via the menu file browser */
|
|
struct
|
|
{
|
|
enum rarch_shader_type preset_type;
|
|
enum rarch_shader_type pass_type;
|
|
|
|
char pass_dir[DIR_MAX_LENGTH];
|
|
char preset_dir[DIR_MAX_LENGTH];
|
|
char preset_file_name[NAME_MAX_LENGTH];
|
|
char pass_file_name[NAME_MAX_LENGTH];
|
|
} last_shader_selection;
|
|
#endif
|
|
|
|
/* Used to cache the last start content
|
|
* loaded via the menu file browser */
|
|
struct
|
|
{
|
|
char directory[DIR_MAX_LENGTH];
|
|
char file_name[NAME_MAX_LENGTH];
|
|
} last_start_content;
|
|
|
|
char menu_state_msg[MENU_LABEL_MAX_LENGTH];
|
|
/* Scratchpad variables. These are used for instance
|
|
* by the filebrowser when having to store intermediary
|
|
* paths (subdirs/previous dirs/current dir/path, etc).
|
|
*/
|
|
char deferred_path[PATH_MAX_LENGTH];
|
|
char scratch_buf[PATH_MAX_LENGTH];
|
|
char scratch2_buf[PATH_MAX_LENGTH];
|
|
char db_playlist_file[PATH_MAX_LENGTH];
|
|
char filebrowser_label[NAME_MAX_LENGTH];
|
|
char detect_content_path[PATH_MAX_LENGTH];
|
|
|
|
/* The Content Downloader directory the user last stepped into. */
|
|
char core_content_dir[NAME_MAX_LENGTH];
|
|
} menu_handle_t;
|
|
|
|
struct menu_state
|
|
{
|
|
/* Timers */
|
|
retro_time_t current_time_us;
|
|
/* Time of the input poll whose state menu_event() reads this
|
|
* frame, and of the poll taken for the next frame. The menu
|
|
* collects its input before polling, so the state it acts on is
|
|
* one poll old; navigation auto-repeat measures a hold between
|
|
* polls so that a stall after the last poll is not counted as
|
|
* time the button was held. */
|
|
retro_time_t input_time_us;
|
|
retro_time_t input_last_time_us;
|
|
menu_input_t input_state; /* retro_time_t alignment */
|
|
|
|
/* How long a held direction has been repeating, in real time: held
|
|
* Left/Right on a number speeds up by it. Set by menu_event(). */
|
|
retro_time_t action_press_time;
|
|
|
|
struct menu_bind_state input_binds; /* uint64_t alignment */
|
|
|
|
gfx_thumbnail_path_data_t *thumbnail_path_data;
|
|
menu_handle_t *driver_data;
|
|
void *userdata;
|
|
const menu_ctx_driver_t *driver_ctx;
|
|
const char **input_dialog_keyboard_buffer;
|
|
|
|
struct
|
|
{
|
|
rarch_setting_t *list_settings;
|
|
menu_list_t *list;
|
|
size_t begin;
|
|
} entries;
|
|
size_t selection_ptr;
|
|
size_t contentless_core_ptr;
|
|
|
|
/* Quick jumping indices with L/R.
|
|
* Rebuilt when parsing directory. */
|
|
struct
|
|
{
|
|
size_t index_list[SCROLL_INDEX_SIZE];
|
|
unsigned index_size;
|
|
unsigned acceleration;
|
|
/* entries this frame's Up or Down moves: set by a held
|
|
* direction's repeat (as many as its speed made due since the last
|
|
* frame); 0 for a press, which moves as the acceleration says */
|
|
unsigned steps;
|
|
enum menu_scroll_mode mode;
|
|
} scroll;
|
|
|
|
/* unsigned alignment */
|
|
unsigned input_dialog_kb_idx;
|
|
unsigned video_screen_selected;
|
|
menu_dialog_t dialog_st;
|
|
enum menu_input_dialog_kb_text_type input_dialog_kb_text_type;
|
|
#ifdef HAVE_RUNAHEAD
|
|
unsigned int runahead_mode;
|
|
#endif
|
|
|
|
/* int16_t alignment */
|
|
menu_input_pointer_hw_state_t input_pointer_hw_state;
|
|
|
|
uint16_t flags;
|
|
#ifdef HAVE_OVERLAY
|
|
uint16_t overlay_types;
|
|
#endif
|
|
|
|
/* When generating a menu list in menu_displaylist_build_list(),
|
|
* the entry with a label matching 'pending_selection' will
|
|
* be selected automatically */
|
|
char pending_selection[PATH_MAX_LENGTH];
|
|
/* Filled with current content path when a core calls
|
|
* RETRO_ENVIRONMENT_SHUTDOWN. Value is required in
|
|
* generic_menu_entry_action(), and must be cached
|
|
* since RETRO_ENVIRONMENT_SHUTDOWN will cause
|
|
* RARCH_PATH_CONTENT to be cleared */
|
|
char pending_env_shutdown_content_path[PATH_MAX_LENGTH];
|
|
/* Path of a configuration file whose load has been deferred
|
|
* (see MENU_ST_FLAG_PENDING_CONFIG_REPLACE). The actual
|
|
* config_replace() is performed from runloop_check_state(),
|
|
* never from within menu iteration */
|
|
char pending_config_path[PATH_MAX_LENGTH];
|
|
|
|
#ifdef HAVE_MENU
|
|
char input_dialog_kb_label_setting[256];
|
|
char input_dialog_kb_label[256];
|
|
|
|
/* The on-screen keyboard, which is the menu's widget: what its keys
|
|
* show, where its cursor is, and which page of keys is up. What it
|
|
* types goes to the frontend's line of text, as a hardware key's
|
|
* does. */
|
|
char *osk_grid[45];
|
|
int osk_ptr;
|
|
enum osk_type osk_idx;
|
|
#endif
|
|
unsigned char kb_key_state[RETROK_LAST];
|
|
|
|
/* The entry generic_menu_iterate() looks at once a frame. Here
|
|
* rather than on its stack: a menu_entry_t is 3872 bytes, which put
|
|
* that frame at 4312 where this tree allows four thousand. One is
|
|
* looked at a time, on the thread that iterates. */
|
|
menu_entry_t iterate_entry;
|
|
};
|
|
|
|
typedef struct menu_content_ctx_defer_info
|
|
{
|
|
void *data;
|
|
const char *dir;
|
|
const char *path;
|
|
const char *menu_label;
|
|
char *s;
|
|
size_t len;
|
|
} menu_content_ctx_defer_info_t;
|
|
|
|
typedef struct menu_ctx_displaylist
|
|
{
|
|
menu_displaylist_info_t *info;
|
|
unsigned type;
|
|
} menu_ctx_displaylist_t;
|
|
|
|
typedef struct menu_ctx_environment
|
|
{
|
|
void *data;
|
|
enum menu_environ_cb type;
|
|
} menu_ctx_environment_t;
|
|
|
|
typedef struct menu_ctx_pointer
|
|
{
|
|
menu_file_list_cbs_t *cbs;
|
|
menu_entry_t *entry;
|
|
unsigned x;
|
|
unsigned y;
|
|
unsigned ptr;
|
|
unsigned action;
|
|
int retcode;
|
|
enum menu_input_pointer_gesture gesture;
|
|
} menu_ctx_pointer_t;
|
|
|
|
typedef struct menu_ctx_bind
|
|
{
|
|
menu_file_list_cbs_t *cbs;
|
|
const char *path;
|
|
const char *label;
|
|
size_t idx;
|
|
unsigned type;
|
|
} menu_ctx_bind_t;
|
|
|
|
#if defined(HAVE_LIBRETRODB)
|
|
typedef struct explore_state explore_state_t;
|
|
#endif
|
|
|
|
typedef struct
|
|
{
|
|
char *runtime_str;
|
|
char *last_played_str;
|
|
enum contentless_core_runtime_status status;
|
|
} contentless_core_runtime_info_t;
|
|
|
|
typedef struct
|
|
{
|
|
char *licenses_str;
|
|
contentless_core_runtime_info_t runtime;
|
|
} contentless_core_info_entry_t;
|
|
|
|
#if defined(HAVE_LIBRETRODB)
|
|
explore_state_t *menu_explore_build_list(const char *directory_playlist,
|
|
const char *directory_database);
|
|
|
|
/* The explore index built in resumable steps. begin() opens the
|
|
* playlist directory; step() advances the build, consulting @within
|
|
* between work items when non-NULL (a playlist entry, an RDB item, a
|
|
* category sort) - returns 1 when complete, 0 when the budget ran out
|
|
* (call again), -1 on failure; end() returns the finished state and
|
|
* frees the handle; abort() abandons a build at any point.
|
|
* menu_explore_build_list() is begin + one unbudgeted step + end. */
|
|
typedef struct explore_build explore_build_t;
|
|
explore_build_t *menu_explore_build_begin(const char *directory_playlist,
|
|
const char *directory_database);
|
|
int menu_explore_build_step(explore_build_t *b,
|
|
bool (*within)(void*), void *ud);
|
|
explore_state_t *menu_explore_build_end(explore_build_t *b);
|
|
void menu_explore_build_abort(explore_build_t *b);
|
|
/* The index's identity for verification: the same collection built in
|
|
* one go and in steps hashes the same (NULL: the installed index); and
|
|
* its size (NULL: the installed index too). */
|
|
uint32_t menu_explore_state_hash(const explore_state_t *state);
|
|
size_t menu_explore_state_entry_count(const explore_state_t *state);
|
|
uintptr_t menu_explore_get_entry_icon(unsigned type);
|
|
ssize_t menu_explore_get_entry_playlist_index(unsigned type,
|
|
playlist_t **playlist, const struct playlist_entry **entry,
|
|
file_list_t *list, size_t *list_pos, size_t *list_size);
|
|
ssize_t menu_explore_set_playlist_thumbnail(unsigned type,
|
|
gfx_thumbnail_path_data_t *thumbnail_path_data); /* returns list index */
|
|
bool menu_explore_is_content_list(void);
|
|
void menu_explore_context_init(void);
|
|
void menu_explore_context_deinit(void);
|
|
void menu_explore_free_state(explore_state_t *state);
|
|
void menu_explore_free(void);
|
|
void menu_explore_set_state(explore_state_t *state);
|
|
#endif
|
|
|
|
const char *menu_driver_ident(void);
|
|
|
|
bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data);
|
|
|
|
void menu_driver_frame(bool menu_is_alive, video_frame_info_t *video_info);
|
|
|
|
int menu_driver_deferred_push_content_list(file_list_t *list);
|
|
|
|
bool menu_driver_init(bool video_is_threaded);
|
|
|
|
/* Rebuilds the menu driver's GPU-side context (textures, fonts) against
|
|
* the running video driver, releasing the old one first. */
|
|
void menu_driver_context_rebuild(void);
|
|
|
|
retro_time_t menu_driver_get_current_time(void);
|
|
|
|
size_t menu_display_timedate(gfx_display_ctx_datetime_t *datetime, char *s, size_t len);
|
|
|
|
size_t menu_display_powerstate(gfx_display_ctx_powerstate_t *powerstate, char *s, size_t len);
|
|
|
|
void menu_display_handle_wallpaper_upload(retro_task_t *task,
|
|
void *task_data,
|
|
void *user_data, const char *err);
|
|
|
|
uintptr_t menu_contentless_cores_get_entry_icon(const char *core_id);
|
|
void menu_contentless_cores_context_init(void);
|
|
void menu_contentless_cores_context_deinit(void);
|
|
void menu_contentless_cores_free(void);
|
|
void menu_contentless_cores_set_runtime(const char *core_id,
|
|
const contentless_core_runtime_info_t *runtime_info);
|
|
void menu_contentless_cores_get_info(const char *core_id,
|
|
const contentless_core_info_entry_t **info);
|
|
void menu_contentless_cores_flush_runtime(void);
|
|
|
|
/* Returns true if search filter is enabled
|
|
* for the specified menu list */
|
|
bool menu_driver_search_filter_enabled(const char *label, unsigned type);
|
|
|
|
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
|
|
void menu_driver_set_last_shader_preset_path(const char *path);
|
|
void menu_driver_set_last_shader_pass_path(const char *path);
|
|
enum rarch_shader_type menu_driver_get_last_shader_preset_type(void);
|
|
void menu_driver_get_last_shader_preset_path(
|
|
const char **directory, const char **file_name);
|
|
void menu_driver_get_last_shader_pass_path(
|
|
const char **directory, const char **file_name);
|
|
#endif
|
|
|
|
void menu_driver_set_pending_selection(const char *pending_selection);
|
|
|
|
struct menu_state *menu_state_get_ptr(void);
|
|
|
|
/* Hands @payload (local UTF-8 paths) to the selected menu entry on
|
|
* the next menu frame. Any thread; takes ownership of @payload.
|
|
* Returns false when the menu is not open, so the caller can fall
|
|
* back to its own handling. */
|
|
bool menu_driver_drop(struct string_list *payload);
|
|
|
|
/* As menu_driver_drop(), for the file:// entries of a text/uri-list.
|
|
* Decodes @list in place. */
|
|
bool menu_driver_drop_uri_list(char *list);
|
|
|
|
int generic_menu_entry_action(void *userdata, menu_entry_t *entry, size_t i, enum menu_action action);
|
|
|
|
void menu_entries_build_scroll_indices(
|
|
struct menu_state *menu_st,
|
|
file_list_t *list);
|
|
|
|
/* Teardown function for the menu driver. */
|
|
void menu_driver_destroy(
|
|
struct menu_state *menu_st);
|
|
|
|
const menu_ctx_driver_t *menu_driver_find_driver(
|
|
settings_t *settings,
|
|
const char *prefix,
|
|
bool verbosity_enabled);
|
|
|
|
/*
|
|
* This function gets called in order to process all input events
|
|
* for the current frame.
|
|
*
|
|
* Sends input code to menu for one frame.
|
|
*
|
|
* It uses as input the local variables 'input' and 'trigger_input'.
|
|
*
|
|
* Mouse and touch input events get processed inside this function.
|
|
*
|
|
* NOTE: 'input' and 'trigger_input' is sourced from the keyboard and/or
|
|
* the gamepad. It does not contain input state derived from the mouse
|
|
* and/or touch - this gets dealt with separately within this function.
|
|
*
|
|
* TODO/FIXME - maybe needs to be overhauled so we can send multiple
|
|
* events per frame if we want to, and we shouldn't send the
|
|
* entire button state either but do a separate event per button
|
|
* state.
|
|
*/
|
|
unsigned menu_event(
|
|
settings_t *settings,
|
|
input_bits_t *p_input,
|
|
input_bits_t *p_trigger_input,
|
|
bool display_kb);
|
|
|
|
/* Gets called when we want to toggle the menu.
|
|
* If the menu is already running, it will be turned off.
|
|
* If the menu is off, then the menu will be started.
|
|
*/
|
|
void menu_driver_toggle(
|
|
void *curr_video_data,
|
|
void *video_driver_data,
|
|
menu_handle_t *menu,
|
|
menu_input_t *menu_input,
|
|
settings_t *settings,
|
|
bool menu_driver_alive,
|
|
bool overlay_alive,
|
|
retro_keyboard_event_t *key_event,
|
|
retro_keyboard_event_t *frontend_key_event,
|
|
bool on);
|
|
|
|
/* Queue a fullscreen file-browser launch; NULL cancels it. */
|
|
bool menu_driver_media_open(const char *path);
|
|
/* Startup presentation is released only by the activated fullscreen view. */
|
|
int menu_driver_media_startup_token(void);
|
|
void menu_driver_media_startup_ready(int token);
|
|
|
|
/* Iterate the menu driver for one frame. */
|
|
bool menu_driver_iterate(
|
|
struct menu_state *menu_st,
|
|
gfx_display_t *p_disp,
|
|
gfx_animation_t *p_anim,
|
|
settings_t *settings,
|
|
enum menu_action action,
|
|
retro_time_t current_time);
|
|
|
|
void menu_display_common_image_upload(void *data,
|
|
void *user_data, unsigned type);
|
|
|
|
size_t menu_update_fullscreen_thumbnail_label(
|
|
char *s, size_t len,
|
|
bool is_quick_menu, const char *title);
|
|
|
|
bool menu_is_running_quick_menu(void);
|
|
|
|
/* "Find a Button by Pressing It": waits for a button of @port's
|
|
* controller and puts the selection on its entry. */
|
|
void menu_input_remap_find_begin(unsigned port);
|
|
/* A combination's buttons set by holding them, on a screen of its own
|
|
* that takes the menu's input meanwhile. False if there is no such
|
|
* combination. */
|
|
bool menu_input_entry_capture_begin(unsigned number);
|
|
|
|
bool menu_input_key_bind_set_mode(
|
|
enum menu_input_binds_ctl_state state, void *data);
|
|
|
|
#ifdef HAVE_RUNAHEAD
|
|
void menu_update_runahead_mode(void);
|
|
#endif
|
|
|
|
size_t menu_playlist_random_selection(
|
|
size_t selection, bool is_explore_list);
|
|
|
|
/* The Playlists tab's Scan: a random playlist row other than
|
|
* @selection. Not menu_playlist_random_selection, which picks an item
|
|
* inside an open playlist or Explore list. */
|
|
size_t menu_playlists_tab_random_selection(size_t selection);
|
|
|
|
void menu_dialog_confirm_set(struct menu_state *menu_st,
|
|
unsigned msg, unsigned cmd);
|
|
void menu_dialog_confirm_clear(struct menu_state *menu_st);
|
|
void menu_dialog_confirm(struct menu_state *menu_st);
|
|
|
|
extern const menu_ctx_driver_t *menu_ctx_drivers[];
|
|
|
|
extern menu_ctx_driver_t menu_ctx_ozone;
|
|
extern menu_ctx_driver_t menu_ctx_rgui;
|
|
extern menu_ctx_driver_t menu_ctx_mui;
|
|
extern menu_ctx_driver_t menu_ctx_xmb;
|
|
|
|
RETRO_END_DECLS
|
|
|
|
#endif
|