Implement in-menu sound effects

This commit is contained in:
Brad Parker 2019-01-27 11:22:16 -05:00
parent 556b7b19de
commit 90db5e7e27
31 changed files with 775 additions and 61 deletions

View File

@ -26,6 +26,7 @@
- MENU: New "ozone" menu driver.
- MENU: Only show CRT SwitchRes if video display server is implemented (Windows/Linux for now)
- MENU: User Interface -> Appearance -> 'Menu Font Green/Blue Color' settings now work properly.
- MENU: Add option to enable in-menu sound effects
- MENU/QT/WIMP: Allow building with MSVC2017
- MENU/QT/WIMP: Add detailed file browser table
- MENU/QT/WIMP: New grid view implementation that is faster and loads thumbnails on-demand

View File

@ -25,6 +25,7 @@
#include <file/file_path.h>
#include <lists/dir_list.h>
#include <string/stdstring.h>
#include <streams/file_stream.h>
#ifdef HAVE_CONFIG_H
#include "../config.h"
@ -35,6 +36,7 @@
#include "../gfx/video_driver.h"
#include "../record/record_driver.h"
#include "../frontend/frontend_driver.h"
#include "../tasks/tasks_internal.h"
#include "../command.h"
#include "../driver.h"
@ -42,9 +44,17 @@
#include "../retroarch.h"
#include "../verbosity.h"
#include "../list_special.h"
#include "../file_path_special.h"
#include "../content.h"
#ifdef HAVE_THREADS
#include <rthreads/rthreads.h>
#endif
#define AUDIO_BUFFER_FREE_SAMPLES_COUNT (8 * 1024)
#define MENU_SOUND_FORMATS "ogg|mod|xm|s3m|mp3|flac"
/**
* db_to_gain:
* @db : Decibels.
@ -185,11 +195,34 @@ static const audio_driver_t *current_audio = NULL;
static void *audio_driver_context_audio_data = NULL;
static bool audio_suspended = false;
static bool audio_is_threaded = false;
#ifdef HAVE_THREADS
static slock_t* s_audio_driver_lock = NULL;
#endif
static void audio_mixer_play_stop_sequential_cb(
audio_mixer_sound_t *sound, unsigned reason);
static void audio_mixer_play_stop_cb(
audio_mixer_sound_t *sound, unsigned reason);
static void audio_mixer_menu_stop_cb(
audio_mixer_sound_t *sound, unsigned reason);
static void audio_driver_lock(void)
{
#ifdef HAVE_THREADS
if (s_audio_driver_lock)
slock_lock(s_audio_driver_lock);
#endif
}
static void audio_driver_unlock(void)
{
#ifdef HAVE_THREADS
if (s_audio_driver_lock)
slock_unlock(s_audio_driver_lock);
#endif
}
enum resampler_quality audio_driver_get_resampler_quality(void)
{
@ -447,6 +480,7 @@ static bool audio_driver_init_internal(bool audio_cb_inited)
#ifdef HAVE_THREADS
if (audio_cb_inited)
{
audio_is_threaded = true;
RARCH_LOG("[Audio]: Starting threaded audio driver ...\n");
if (!audio_init_thread(
&current_audio,
@ -465,6 +499,7 @@ static bool audio_driver_init_internal(bool audio_cb_inited)
else
#endif
{
audio_is_threaded = false;
audio_driver_context_audio_data =
current_audio->init(*settings->arrays.audio_device ?
settings->arrays.audio_device : NULL,
@ -507,6 +542,15 @@ static bool audio_driver_init_internal(bool audio_cb_inited)
audio_source_ratio_original = audio_source_ratio_current =
(double)settings->uints.audio_out_rate / audio_driver_input;
#ifdef HAVE_THREADS
if (s_audio_driver_lock)
slock_free(s_audio_driver_lock);
s_audio_driver_lock = slock_new();
#endif
audio_resampler_lock_init();
audio_resampler_lock();
if (!retro_resampler_realloc(
&audio_driver_resampler_data,
&audio_driver_resampler,
@ -519,6 +563,8 @@ static bool audio_driver_init_internal(bool audio_cb_inited)
audio_driver_active = false;
}
audio_resampler_unlock();
aud_inp_data = (float*)malloc(max_bufsamples * sizeof(float));
retro_assert(aud_inp_data != NULL);
@ -589,9 +635,13 @@ void audio_driver_set_nonblocking_state(bool enable)
audio_driver_context_audio_data,
settings->bools.audio_sync ? enable : true);
audio_driver_lock();
audio_driver_chunk_size = enable ?
audio_driver_chunk_nonblock_size :
audio_driver_chunk_block_size;
audio_driver_unlock();
}
/**
@ -609,6 +659,7 @@ static void audio_driver_flush(const int16_t *data, size_t samples)
bool is_paused = false;
bool is_idle = false;
bool is_slowmotion = false;
bool is_active = false;
const void *output_data = NULL;
unsigned output_frames = 0;
float audio_volume_gain = !audio_driver_mute_enable ?
@ -617,9 +668,13 @@ static void audio_driver_flush(const int16_t *data, size_t samples)
src_data.data_out = NULL;
src_data.output_frames = 0;
recording_driver_lock();
if (recording_data)
recording_push_audio(data, samples);
recording_driver_unlock();
runloop_get_status(&is_paused, &is_idle, &is_slowmotion,
&is_perfcnt_enable);
@ -629,9 +684,13 @@ static void audio_driver_flush(const int16_t *data, size_t samples)
!audio_driver_output_samples_buf)
return;
audio_driver_lock();
convert_s16_to_float(audio_driver_input_data, data, samples,
audio_volume_gain);
audio_driver_unlock();
src_data.data_in = audio_driver_input_data;
src_data.input_frames = samples >> 1;
@ -695,9 +754,15 @@ static void audio_driver_flush(const int16_t *data, size_t samples)
src_data.ratio *= settings->floats.slowmotion_ratio;
}
audio_driver_resampler->process(audio_driver_resampler_data, &src_data);
audio_driver_lock();
if (audio_mixer_active)
audio_resampler_lock();
audio_driver_resampler->process(audio_driver_resampler_data, &src_data);
audio_resampler_unlock();
is_active = audio_mixer_active;
if (is_active)
{
bool override = audio_driver_mixer_mute_enable ? true :
(audio_driver_mixer_volume_gain != 1.0f) ? true : false;
@ -707,6 +772,8 @@ static void audio_driver_flush(const int16_t *data, size_t samples)
src_data.output_frames, mixer_gain, override);
}
audio_driver_unlock();
output_data = audio_driver_output_samples_buf;
output_frames = (unsigned)src_data.output_frames;
@ -721,9 +788,13 @@ static void audio_driver_flush(const int16_t *data, size_t samples)
output_frames *= sizeof(int16_t);
}
audio_driver_lock();
if (current_audio->write(audio_driver_context_audio_data,
output_data, output_frames * 2) < 0)
audio_driver_active = false;
audio_driver_unlock();
}
/**
@ -735,14 +806,24 @@ static void audio_driver_flush(const int16_t *data, size_t samples)
**/
void audio_driver_sample(int16_t left, int16_t right)
{
audio_driver_lock();
if (audio_suspended)
{
audio_driver_unlock();
return;
}
audio_driver_output_samples_conv_buf[audio_driver_data_ptr++] = left;
audio_driver_output_samples_conv_buf[audio_driver_data_ptr++] = right;
if (audio_driver_data_ptr < audio_driver_chunk_size)
{
audio_driver_unlock();
return;
}
audio_driver_unlock();
audio_driver_flush(audio_driver_output_samples_conv_buf,
audio_driver_data_ptr);
@ -753,9 +834,8 @@ void audio_driver_sample(int16_t left, int16_t right)
void audio_driver_menu_sample(void)
{
static int16_t samples_buf[1024] = {0};
struct retro_system_av_info
*av_info = video_viewport_get_system_av_info();
const struct retro_system_timing *info =
struct retro_system_av_info *av_info = video_viewport_get_system_av_info();
const struct retro_system_timing *info =
(const struct retro_system_timing*)&av_info->timing;
unsigned sample_count = (info->sample_rate / info->fps) * 2;
while (sample_count > 1024)
@ -966,10 +1046,13 @@ bool audio_driver_find_driver(void)
void audio_driver_deinit_resampler(void)
{
audio_resampler_lock();
if (audio_driver_resampler && audio_driver_resampler_data)
audio_driver_resampler->free(audio_driver_resampler_data);
audio_driver_resampler = NULL;
audio_driver_resampler_data = NULL;
audio_resampler_unlock();
audio_resampler_lock_free();
}
bool audio_driver_free_devices_list(void)
@ -1095,6 +1178,28 @@ static void audio_mixer_play_stop_cb(
}
}
static void audio_mixer_menu_stop_cb(
audio_mixer_sound_t *sound, unsigned reason)
{
int idx = audio_mixer_find_index(sound);
switch (reason)
{
case AUDIO_MIXER_SOUND_FINISHED:
if (idx >= 0)
{
unsigned i = (unsigned)idx;
audio_mixer_streams[i].state = AUDIO_STREAM_STATE_STOPPED;
audio_mixer_streams[i].volume = 0.0f;
}
break;
case AUDIO_MIXER_SOUND_STOPPED:
break;
case AUDIO_MIXER_SOUND_REPEATED:
break;
}
}
static void audio_mixer_play_stop_sequential_cb(
audio_mixer_sound_t *sound, unsigned reason)
{
@ -1113,9 +1218,9 @@ static void audio_mixer_play_stop_sequential_cb(
free(audio_mixer_streams[i].name);
if (i < AUDIO_MIXER_MAX_STREAMS)
audio_mixer_streams[i].type = AUDIO_STREAM_TYPE_USER;
audio_mixer_streams[i].stream_type = AUDIO_STREAM_TYPE_USER;
else
audio_mixer_streams[i].type = AUDIO_STREAM_TYPE_SYSTEM;
audio_mixer_streams[i].stream_type = AUDIO_STREAM_TYPE_SYSTEM;
audio_mixer_streams[i].name = NULL;
audio_mixer_streams[i].state = AUDIO_STREAM_STATE_NONE;
@ -1243,17 +1348,22 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params)
break;
}
audio_driver_lock();
audio_mixer_active = true;
audio_mixer_streams[free_slot].name = !string_is_empty(params->basename) ? strdup(params->basename) : NULL;
audio_mixer_streams[free_slot].name = !string_is_empty(params->basename) ? strdup(params->basename) : NULL;
audio_mixer_streams[free_slot].buf = buf;
audio_mixer_streams[free_slot].handle = handle;
audio_mixer_streams[free_slot].voice = voice;
audio_mixer_streams[free_slot].type = params->stream_type;
audio_mixer_streams[free_slot].stream_type = params->stream_type;
audio_mixer_streams[free_slot].type = params->type;
audio_mixer_streams[free_slot].state = params->state;
audio_mixer_streams[free_slot].volume = params->volume;
audio_mixer_streams[free_slot].stop_cb = stop_cb;
audio_driver_unlock();
return true;
}
@ -1291,12 +1401,128 @@ static void audio_driver_mixer_play_stream_internal(unsigned i, unsigned type)
audio_mixer_streams[i].state = (enum audio_mixer_state)type;
}
static void audio_driver_load_menu_bgm_callback(void *task_data, void *user_data, const char *error)
{
bool contentless = false;
bool is_inited = false;
content_get_status(&contentless, &is_inited);
if (!is_inited)
audio_driver_mixer_play_menu_sound_looped(AUDIO_MIXER_SYSTEM_SLOT_BGM);
}
void audio_driver_load_menu_sounds(void)
{
settings_t *settings = config_get_ptr();
char *sounds_path = NULL;
char *sounds_fallback_path = NULL;
const char *path_ok = NULL;
const char *path_cancel = NULL;
const char *path_notice = NULL;
const char *path_bgm = NULL;
struct string_list *list = NULL;
struct string_list *list_fallback = NULL;
int i = 0;
sounds_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
sounds_fallback_path = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
sounds_path[0] = sounds_fallback_path[0] = '\0';
fill_pathname_join(
sounds_fallback_path,
settings->paths.directory_assets,
"sounds",
PATH_MAX_LENGTH * sizeof(char)
);
fill_pathname_application_special(sounds_path, PATH_MAX_LENGTH * sizeof(char), APPLICATION_SPECIAL_DIRECTORY_ASSETS_SOUNDS);
list = dir_list_new(sounds_path, MENU_SOUND_FORMATS, false, false, false, false);
list_fallback = dir_list_new(sounds_fallback_path, MENU_SOUND_FORMATS, false, false, false, false);
if (!list)
{
list = list_fallback;
list_fallback = NULL;
}
if (!list || list->size == 0)
goto end;
if (list_fallback && list_fallback->size > 0)
{
for (i = 0; i < list_fallback->size; i++)
{
if (list->size == 0 || !string_list_find_elem(list, list_fallback->elems[i].data))
{
union string_list_elem_attr attr = {0};
string_list_append(list, list_fallback->elems[i].data, attr);
}
}
}
for (i = 0; i < list->size; i++)
{
const char *path = list->elems[i].data;
const char *ext = path_get_extension(path);
char basename_noext[PATH_MAX_LENGTH];
basename_noext[0] = '\0';
fill_pathname_base_noext(basename_noext, path, sizeof(basename_noext));
if (audio_driver_mixer_extension_supported(ext))
{
if (string_is_equal_noncase(basename_noext, "ok"))
path_ok = path;
if (string_is_equal_noncase(basename_noext, "cancel"))
path_cancel = path;
if (string_is_equal_noncase(basename_noext, "notice"))
path_notice = path;
if (string_is_equal_noncase(basename_noext, "bgm"))
path_bgm = path;
}
}
if (path_ok && settings->bools.audio_enable_menu_ok)
task_push_audio_mixer_load(path_ok, NULL, NULL, true, AUDIO_MIXER_SLOT_SELECTION_MANUAL, AUDIO_MIXER_SYSTEM_SLOT_OK);
if (path_cancel && settings->bools.audio_enable_menu_cancel)
task_push_audio_mixer_load(path_cancel, NULL, NULL, true, AUDIO_MIXER_SLOT_SELECTION_MANUAL, AUDIO_MIXER_SYSTEM_SLOT_CANCEL);
if (path_notice && settings->bools.audio_enable_menu_notice)
task_push_audio_mixer_load(path_notice, NULL, NULL, true, AUDIO_MIXER_SLOT_SELECTION_MANUAL, AUDIO_MIXER_SYSTEM_SLOT_NOTICE);
if (path_bgm && settings->bools.audio_enable_menu_bgm)
task_push_audio_mixer_load(path_bgm, audio_driver_load_menu_bgm_callback, NULL, true, AUDIO_MIXER_SLOT_SELECTION_MANUAL, AUDIO_MIXER_SYSTEM_SLOT_BGM);
end:
if (list)
string_list_free(list);
if (list_fallback)
string_list_free(list_fallback);
if (sounds_path)
free(sounds_path);
if (sounds_fallback_path)
free(sounds_fallback_path);
}
void audio_driver_mixer_play_stream(unsigned i)
{
audio_mixer_streams[i].stop_cb = audio_mixer_play_stop_cb;
audio_driver_mixer_play_stream_internal(i, AUDIO_STREAM_STATE_PLAYING);
}
void audio_driver_mixer_play_menu_sound_looped(unsigned i)
{
audio_mixer_streams[i].stop_cb = audio_mixer_menu_stop_cb;
audio_driver_mixer_play_stream_internal(i, AUDIO_STREAM_STATE_PLAYING_LOOPED);
}
void audio_driver_mixer_play_menu_sound(unsigned i)
{
audio_mixer_streams[i].stop_cb = audio_mixer_menu_stop_cb;
audio_driver_mixer_play_stream_internal(i, AUDIO_STREAM_STATE_PLAYING);
}
void audio_driver_mixer_play_stream_looped(unsigned i)
{
audio_mixer_streams[i].stop_cb = audio_mixer_play_stop_cb;
@ -1421,6 +1647,9 @@ bool audio_driver_deinit(void)
{
audio_driver_mixer_deinit();
audio_driver_free_devices_list();
slock_free(s_audio_driver_lock);
s_audio_driver_lock = NULL;
if (!audio_driver_deinit_internal())
return false;
return true;

View File

@ -37,7 +37,16 @@ RETRO_BEGIN_DECLS
#define AUDIO_MIXER_MAX_STREAMS 16
#define AUDIO_MIXER_MAX_SYSTEM_STREAMS (AUDIO_MIXER_MAX_STREAMS+4)
#define AUDIO_MIXER_MAX_SYSTEM_STREAMS (AUDIO_MIXER_MAX_STREAMS + 4)
/* do not define more than (MAX_SYSTEM_STREAMS - MAX_STREAMS) */
enum audio_mixer_system_slot
{
AUDIO_MIXER_SYSTEM_SLOT_OK = AUDIO_MIXER_MAX_STREAMS,
AUDIO_MIXER_SYSTEM_SLOT_CANCEL,
AUDIO_MIXER_SYSTEM_SLOT_NOTICE,
AUDIO_MIXER_SYSTEM_SLOT_BGM
};
enum audio_action
{
@ -315,6 +324,10 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params);
void audio_driver_mixer_play_stream(unsigned i);
void audio_driver_mixer_play_menu_sound(unsigned i);
void audio_driver_mixer_play_menu_sound_looped(unsigned i);
void audio_driver_mixer_play_stream_sequential(unsigned i);
void audio_driver_mixer_play_stream_looped(unsigned i);
@ -335,6 +348,8 @@ const char *audio_driver_mixer_get_stream_name(unsigned i);
bool compute_audio_buffer_statistics(audio_statistics_t *stats);
void audio_driver_load_menu_sounds(void);
extern audio_driver_t audio_rsound;
extern audio_driver_t audio_audioio;
extern audio_driver_t audio_oss;

View File

@ -508,6 +508,13 @@ static const bool video_3ds_lcd_bottom = true;
/* Will enable audio or not. */
static const bool audio_enable = true;
/* Enable menu audio sounds. */
static const bool audio_enable_menu = false;
static const bool audio_enable_menu_ok = false;
static const bool audio_enable_menu_cancel = false;
static const bool audio_enable_menu_notice = false;
static const bool audio_enable_menu_bgm = false;
/* Output samplerate. */
#ifdef GEKKO
static const unsigned out_rate = 32000;

View File

@ -1395,7 +1395,11 @@ static struct config_bool_setting *populate_settings_bool(settings_t *settings,
SETTING_BOOL("keyboard_gamepad_enable", &settings->bools.input_keyboard_gamepad_enable, true, true, false);
SETTING_BOOL("core_set_supports_no_game_enable", &settings->bools.set_supports_no_game_enable, true, true, false);
SETTING_BOOL("audio_enable", &settings->bools.audio_enable, true, audio_enable, false);
SETTING_BOOL("audio_enable_menu", &settings->bools.audio_enable_menu, true, false, false);
SETTING_BOOL("audio_enable_menu", &settings->bools.audio_enable_menu, true, audio_enable_menu, false);
SETTING_BOOL("audio_enable_menu_ok", &settings->bools.audio_enable_menu_ok, true, audio_enable_menu_ok, false);
SETTING_BOOL("audio_enable_menu_cancel", &settings->bools.audio_enable_menu_cancel, true, audio_enable_menu_cancel, false);
SETTING_BOOL("audio_enable_menu_notice", &settings->bools.audio_enable_menu_notice, true, audio_enable_menu_notice, false);
SETTING_BOOL("audio_enable_menu_bgm", &settings->bools.audio_enable_menu_bgm, true, audio_enable_menu_bgm, false);
SETTING_BOOL("audio_mute_enable", audio_get_bool_ptr(AUDIO_ACTION_MUTE_ENABLE), true, false, false);
SETTING_BOOL("audio_mixer_mute_enable", audio_get_bool_ptr(AUDIO_ACTION_MIXER_MUTE_ENABLE), true, false, false);
SETTING_BOOL("location_allow", &settings->bools.location_allow, true, false, false);

View File

@ -110,6 +110,10 @@ typedef struct settings
/* Audio */
bool audio_enable;
bool audio_enable_menu;
bool audio_enable_menu_ok;
bool audio_enable_menu_cancel;
bool audio_enable_menu_notice;
bool audio_enable_menu_bgm;
bool audio_sync;
bool audio_rate_control;
bool audio_wasapi_exclusive_mode;

View File

@ -51,6 +51,10 @@
#include <retro_miscellaneous.h>
#include <encodings/utf.h>
#ifdef HAVE_MENU
#include <menu/menu_driver.h>
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@ -238,6 +242,70 @@ void fill_pathname_application_special(char *s,
free(s1);
}
}
#endif
break;
case APPLICATION_SPECIAL_DIRECTORY_ASSETS_SOUNDS:
{
#ifdef HAVE_MENU
settings_t *settings = config_get_ptr();
const char *menu_ident = settings->arrays.menu_driver;
char *s1 = (char*)calloc(1, PATH_MAX_LENGTH * sizeof(char));
if (string_is_equal(menu_ident, "xmb"))
{
fill_pathname_application_special(s1, PATH_MAX_LENGTH * sizeof(char), APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB);
if (!string_is_empty(s1))
strlcat(s1, "/sounds", PATH_MAX_LENGTH * sizeof(char));
}
else if (string_is_equal(menu_ident, "glui"))
{
fill_pathname_application_special(s1, PATH_MAX_LENGTH * sizeof(char), APPLICATION_SPECIAL_DIRECTORY_ASSETS_MATERIALUI);
if (!string_is_empty(s1))
strlcat(s1, "/sounds", PATH_MAX_LENGTH * sizeof(char));
}
else if (string_is_equal(menu_ident, "ozone"))
{
fill_pathname_application_special(s1, PATH_MAX_LENGTH * sizeof(char), APPLICATION_SPECIAL_DIRECTORY_ASSETS_OZONE);
if (!string_is_empty(s1))
strlcat(s1, "/sounds", PATH_MAX_LENGTH * sizeof(char));
}
if (string_is_empty(s1))
{
fill_pathname_join(
s1,
settings->paths.directory_assets,
"sounds",
PATH_MAX_LENGTH * sizeof(char)
);
}
strlcpy(s, s1, len);
free(s1);
#endif
}
break;
case APPLICATION_SPECIAL_DIRECTORY_ASSETS_OZONE:
#ifdef HAVE_OZONE
{
char *s1 = (char*)malloc(PATH_MAX_LENGTH * sizeof(char));
settings_t *settings = config_get_ptr();
s1[0] = '\0';
fill_pathname_join(
s1,
settings->paths.directory_assets,
"ozone",
PATH_MAX_LENGTH * sizeof(char)
);
strlcpy(s, s1, len);
free(s1);
}
#endif
break;
case APPLICATION_SPECIAL_DIRECTORY_ASSETS_XMB:

View File

@ -111,6 +111,8 @@ enum application_special_type
APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH,
APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH_FONT,
APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH_ICONS,
APPLICATION_SPECIAL_DIRECTORY_ASSETS_OZONE,
APPLICATION_SPECIAL_DIRECTORY_ASSETS_SOUNDS,
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_CHEEVOS_BADGES,
APPLICATION_SPECIAL_DIRECTORY_THUMBNAILS_DISCORD_AVATARS
};

View File

@ -38,6 +38,7 @@
#include "../paths.h"
#include "../retroarch.h"
#include "../verbosity.h"
#include "../record/record_driver.h"
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
#include <objbase.h>
@ -91,6 +92,7 @@ void main_exit(void *args)
driver_ctl(RARCH_DRIVER_CTL_DEINIT, NULL);
ui_companion_driver_free();
frontend_driver_free();
recording_driver_lock_free();
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
CoUninitialize();

View File

@ -1422,6 +1422,8 @@ bool video_driver_cached_frame(void)
{
void *recording = recording_driver_get_data_ptr();
recording_driver_lock();
/* Cannot allow recording when pushing duped frames. */
recording_data = NULL;
@ -1433,6 +1435,8 @@ bool video_driver_cached_frame(void)
recording_data = recording;
recording_driver_unlock();
return true;
}

View File

@ -305,6 +305,8 @@ MSG_HASH(MENU_ENUM_LABEL_DEFERRED_AUDIO_SETTINGS_LIST,
"deferred_audio_settings_list")
MSG_HASH(MENU_ENUM_LABEL_DEFERRED_AUDIO_MIXER_SETTINGS_LIST,
"deferred_audio_mixer_settings_list")
MSG_HASH(MENU_ENUM_LABEL_DEFERRED_MENU_SOUNDS_LIST,
"deferred_menu_sounds_list")
MSG_HASH(MENU_ENUM_LABEL_DEFERRED_CONFIGURATION_SETTINGS_LIST,
"deferred_configuration_settings_list")
MSG_HASH(MENU_ENUM_LABEL_DEFERRED_CORE_CONTENT_DIRS_LIST,
@ -1609,6 +1611,8 @@ MSG_HASH(MENU_ENUM_LABEL_AUDIO_ENABLE_MENU,
"audio_enable_menu")
MSG_HASH(MENU_ENUM_LABEL_AUDIO_MIXER_SETTINGS,
"audio_mixer_settings")
MSG_HASH(MENU_ENUM_LABEL_MENU_SOUNDS,
"menu_sounds")
MSG_HASH(MENU_ENUM_LABEL_DEFERRED_MIXER_STREAM_SETTINGS_LIST,
"deferred_mixer_stream_settings_list")
MSG_HASH(MENU_ENUM_LABEL_QUICK_MENU_OVERRIDE_OPTIONS,
@ -1769,3 +1773,11 @@ MSG_HASH(MENU_ENUM_LABEL_VIDEO_3DS_LCD_BOTTOM,
"video_3ds_lcd_bottom")
MSG_HASH(MENU_ENUM_LABEL_PLAYLIST_USE_OLD_FORMAT,
"playlist_use_old_format")
MSG_HASH(MENU_ENUM_LABEL_MENU_SOUND_OK,
"menu_sound_ok")
MSG_HASH(MENU_ENUM_LABEL_MENU_SOUND_CANCEL,
"menu_sound_cancel")
MSG_HASH(MENU_ENUM_LABEL_MENU_SOUND_NOTICE,
"menu_sound_notice")
MSG_HASH(MENU_ENUM_LABEL_MENU_SOUND_BGM,
"menu_sound_bgm")

View File

@ -8112,3 +8112,23 @@ MSG_HASH(
MENU_ENUM_LABEL_VALUE_PLAYLIST_USE_OLD_FORMAT,
"Save playlists using old format"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_MENU_SOUNDS,
"Menu Sounds"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_MENU_SOUND_OK,
"Enable OK sound"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_MENU_SOUND_CANCEL,
"Enable cancel sound"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_MENU_SOUND_NOTICE,
"Enable notice sound"
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_MENU_SOUND_BGM,
"Enable BGM sound"
)

View File

@ -188,7 +188,7 @@ struct audio_mixer_voice
} types;
};
static struct audio_mixer_voice s_voices[AUDIO_MIXER_MAX_VOICES] = {0};
static struct audio_mixer_voice s_voices[AUDIO_MIXER_MAX_VOICES] = {{0}};
static unsigned s_rate = 0;
#ifdef HAVE_THREADS
@ -318,6 +318,8 @@ void audio_mixer_init(unsigned rate)
s_voices[i].type = AUDIO_MIXER_TYPE_NONE;
#ifdef HAVE_THREADS
if (s_locker)
slock_free(s_locker);
s_locker = slock_new();
#endif
}
@ -551,17 +553,18 @@ static bool audio_mixer_play_ogg(
if (!ogg_buffer)
{
resamp->free(resampler_data);
if (resamp && resampler_data)
resamp->free(resampler_data);
goto error;
}
/* "system" menu sounds may reuse the same voice without freeing anything first, so do that here if needed */
if (voice->types.ogg.buffer)
memalign_free(voice->types.ogg.buffer);
if (voice->types.ogg.stream)
stb_vorbis_close(voice->types.ogg.stream);
if (voice->types.ogg.resampler && voice->types.ogg.resampler_data)
voice->types.ogg.resampler->free(voice->types.ogg.resampler_data);
if (voice->types.ogg.buffer)
memalign_free(voice->types.ogg.buffer);
voice->types.ogg.resampler = resamp;
voice->types.ogg.resampler_data = resampler_data;
@ -635,10 +638,11 @@ static bool audio_mixer_play_mod(
goto error;
}
if (voice->types.mod.buffer)
memalign_free(voice->types.mod.buffer);
/* FIXME: stopping and then starting a mod stream will crash here in dispose_replay (ASAN says struct replay is misaligned?) */
if (voice->types.mod.stream)
dispose_replay(voice->types.mod.stream);
if (voice->types.mod.buffer)
memalign_free(voice->types.mod.buffer);
voice->types.mod.buffer = (int*)mod_buffer;
voice->types.mod.buf_samples = buf_samples;
@ -696,12 +700,12 @@ static bool audio_mixer_play_flac(
goto error;
}
if (voice->types.flac.buffer)
memalign_free(voice->types.flac.buffer);
if (voice->types.flac.stream)
drflac_close(voice->types.flac.stream);
if (voice->types.flac.resampler && voice->types.flac.resampler_data)
voice->types.flac.resampler->free(voice->types.flac.resampler_data);
if (voice->types.flac.buffer)
memalign_free(voice->types.flac.buffer);
voice->types.flac.resampler = resamp;
voice->types.flac.resampler_data = resampler_data;
@ -761,15 +765,16 @@ static bool audio_mixer_play_mp3(
if (!mp3_buffer)
{
resamp->free(resampler_data);
if (resamp && resampler_data)
resamp->free(resampler_data);
goto error;
}
/* "system" menu sounds may reuse the same voice without freeing anything first, so do that here if needed */
if (voice->types.mp3.buffer)
memalign_free(voice->types.mp3.buffer);
if (voice->types.mp3.resampler && voice->types.mp3.resampler_data)
voice->types.mp3.resampler->free(voice->types.mp3.resampler_data);
if (voice->types.mp3.buffer)
memalign_free(voice->types.mp3.buffer);
voice->types.mp3.resampler = resamp;
voice->types.mp3.resampler_data = resampler_data;
@ -801,6 +806,8 @@ audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, bool repeat,
slock_lock(s_locker);
#endif
audio_resampler_lock();
for (i = 0; i < AUDIO_MIXER_MAX_VOICES; i++, voice++)
{
if (voice->type != AUDIO_MIXER_TYPE_NONE)
@ -849,6 +856,8 @@ audio_mixer_voice_t* audio_mixer_play(audio_mixer_sound_t* sound, bool repeat,
else
voice = NULL;
audio_resampler_unlock();
#ifdef HAVE_THREADS
slock_unlock(s_locker);
#endif
@ -863,13 +872,13 @@ void audio_mixer_stop(audio_mixer_voice_t* voice)
if (voice)
{
stop_cb = voice->stop_cb;
sound = voice->sound;
#ifdef HAVE_THREADS
slock_lock(s_locker);
#endif
stop_cb = voice->stop_cb;
sound = voice->sound;
voice->type = AUDIO_MIXER_TYPE_NONE;
#ifdef HAVE_THREADS
@ -971,7 +980,9 @@ again:
info.ratio = voice->types.ogg.ratio;
if (voice->types.ogg.resampler)
{
voice->types.ogg.resampler->process(voice->types.ogg.resampler_data, &info);
}
else
memcpy(voice->types.ogg.buffer, temp_buffer, temp_samples * sizeof(float));
voice->types.ogg.position = 0;
@ -1118,7 +1129,9 @@ again:
info.ratio = voice->types.flac.ratio;
if (voice->types.flac.resampler)
{
voice->types.flac.resampler->process(voice->types.flac.resampler_data, &info);
}
else
memcpy(voice->types.flac.buffer, temp_buffer, temp_samples * sizeof(float));
voice->types.flac.position = 0;
@ -1231,6 +1244,8 @@ void audio_mixer_mix(float* buffer, size_t num_frames, float volume_override, bo
slock_lock(s_locker);
#endif
audio_resampler_lock();
for (i = 0; i < AUDIO_MIXER_MAX_VOICES; i++, voice++)
{
float volume = (override) ? volume_override : voice->volume;
@ -1265,10 +1280,6 @@ void audio_mixer_mix(float* buffer, size_t num_frames, float volume_override, bo
}
}
#ifdef HAVE_THREADS
slock_unlock(s_locker);
#endif
for (j = 0, sample = buffer; j < num_frames; j++, sample++)
{
if (*sample < -1.0f)
@ -1276,6 +1287,12 @@ void audio_mixer_mix(float* buffer, size_t num_frames, float volume_override, bo
else if (*sample > 1.0f)
*sample = 1.0f;
}
audio_resampler_unlock();
#ifdef HAVE_THREADS
slock_unlock(s_locker);
#endif
}
float audio_mixer_voice_get_volume(audio_mixer_voice_t *voice)

View File

@ -28,6 +28,14 @@
#include <audio/audio_resampler.h>
#ifdef HAVE_THREADS
#include <rthreads/rthreads.h>
#endif
#ifdef HAVE_THREADS
static slock_t* s_resampler_lock = NULL;
#endif
static const retro_resampler_t *resampler_drivers[] = {
&sinc_resampler,
#ifdef HAVE_CC_RESAMPLER
@ -170,3 +178,38 @@ bool retro_resampler_realloc(void **re, const retro_resampler_t **backend,
return true;
}
void audio_resampler_lock_init(void)
{
#ifdef HAVE_THREADS
if (s_resampler_lock)
slock_free(s_resampler_lock);
s_resampler_lock = slock_new();
#endif
}
void audio_resampler_lock_free(void)
{
#ifdef HAVE_THREADS
if (s_resampler_lock)
slock_free(s_resampler_lock);
s_resampler_lock = NULL;
#endif
}
void audio_resampler_lock(void)
{
#ifdef HAVE_THREADS
if (s_resampler_lock)
slock_lock(s_resampler_lock);
#endif
}
void audio_resampler_unlock(void)
{
#ifdef HAVE_THREADS
if (s_resampler_lock)
slock_unlock(s_resampler_lock);
#endif
}

View File

@ -190,6 +190,14 @@ const char *audio_resampler_driver_find_ident(int index);
bool retro_resampler_realloc(void **re, const retro_resampler_t **backend,
const char *ident, enum resampler_quality quality, double bw_ratio);
void audio_resampler_lock_init(void);
void audio_resampler_lock(void);
void audio_resampler_unlock(void);
void audio_resampler_lock_free(void);
RETRO_END_DECLS
#endif

View File

@ -18,6 +18,7 @@
#include "../menu_driver.h"
#include "../menu_cbs.h"
#include "../configuration.h"
#include "../../msg_hash.h"
#include "../../managers/cheat_manager.h"
@ -36,12 +37,16 @@ int action_cancel_pop_default(const char *path,
size_t new_selection_ptr;
const char *menu_label = NULL;
enum msg_hash_enums enum_idx = MSG_UNKNOWN;
settings_t *settings = config_get_ptr();
(void)path;
(void)label;
(void)type;
(void)idx;
if (settings->bools.audio_enable_menu && settings->bools.audio_enable_menu_cancel)
audio_driver_mixer_play_menu_sound(AUDIO_MIXER_SYSTEM_SLOT_CANCEL);
menu_entries_get_last_stack(NULL, &menu_label, NULL, &enum_idx, NULL);
if (!string_is_empty(menu_label))

View File

@ -152,7 +152,7 @@ generic_deferred_push(deferred_push_menu_views_settings_list, DISPLAYLIST_
generic_deferred_push(deferred_push_quick_menu_views_settings_list, DISPLAYLIST_QUICK_MENU_VIEWS_SETTINGS_LIST)
generic_deferred_push(deferred_push_menu_settings_list, DISPLAYLIST_MENU_SETTINGS_LIST)
generic_deferred_push(deferred_push_user_interface_settings_list, DISPLAYLIST_USER_INTERFACE_SETTINGS_LIST)
generic_deferred_push(deferred_push_power_management_settings_list, DISPLAYLIST_POWER_MANAGEMENT_SETTINGS_LIST)
generic_deferred_push(deferred_push_power_management_settings_list, DISPLAYLIST_POWER_MANAGEMENT_SETTINGS_LIST)
generic_deferred_push(deferred_push_retro_achievements_settings_list,DISPLAYLIST_RETRO_ACHIEVEMENTS_SETTINGS_LIST)
generic_deferred_push(deferred_push_updater_settings_list, DISPLAYLIST_UPDATER_SETTINGS_LIST)
generic_deferred_push(deferred_push_wifi_settings_list, DISPLAYLIST_WIFI_SETTINGS_LIST)
@ -177,6 +177,7 @@ generic_deferred_push(deferred_push_rdb_entry_detail, DISPLAYLIST_
generic_deferred_push(deferred_push_rpl_entry_actions, DISPLAYLIST_HORIZONTAL_CONTENT_ACTIONS)
generic_deferred_push(deferred_push_core_list_deferred, DISPLAYLIST_CORES_SUPPORTED)
generic_deferred_push(deferred_push_core_collection_list_deferred, DISPLAYLIST_CORES_COLLECTION_SUPPORTED)
generic_deferred_push(deferred_push_menu_sounds_list, DISPLAYLIST_MENU_SOUNDS_LIST)
#ifdef HAVE_NETWORKING
generic_deferred_push(deferred_push_thumbnails_updater_list, DISPLAYLIST_THUMBNAILS_UPDATER)
@ -741,6 +742,11 @@ static int menu_cbs_init_bind_deferred_push_compare_label(
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_power_management_settings_list);
return 0;
}
else if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_MENU_SOUNDS_LIST)))
{
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_menu_sounds_list);
return 0;
}
else if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_RETRO_ACHIEVEMENTS_SETTINGS_LIST)))
{
BIND_ACTION_DEFERRED_PUSH(cbs, deferred_push_retro_achievements_settings_list);

View File

@ -20,6 +20,8 @@
#include "../widgets/menu_dialog.h"
#include "../../configuration.h"
#ifndef BIND_ACTION_INFO
#define BIND_ACTION_INFO(cbs, name) \
cbs->action_info = name; \
@ -35,6 +37,7 @@ static int action_info_default(unsigned type, const char *label)
menu_displaylist_info_t info;
file_list_t *menu_stack = menu_entries_get_menu_stack_ptr(0);
size_t selection = menu_navigation_get_selection();
settings_t *settings = config_get_ptr();
menu_displaylist_info_init(&info);
@ -47,6 +50,9 @@ static int action_info_default(unsigned type, const char *label)
if (!menu_displaylist_ctl(DISPLAYLIST_HELP, &info))
goto error;
if (settings->bools.audio_enable_menu && settings->bools.audio_enable_menu_notice)
audio_driver_mixer_play_menu_sound(AUDIO_MIXER_SYSTEM_SLOT_NOTICE);
if (!menu_displaylist_process(&info))
goto error;

View File

@ -212,6 +212,8 @@ static enum msg_hash_enums action_ok_dl_to_enum(unsigned lbl)
return MENU_ENUM_LABEL_DEFERRED_USER_INTERFACE_SETTINGS_LIST;
case ACTION_OK_DL_POWER_MANAGEMENT_SETTINGS_LIST:
return MENU_ENUM_LABEL_DEFERRED_POWER_MANAGEMENT_SETTINGS_LIST;
case ACTION_OK_DL_MENU_SOUNDS_LIST:
return MENU_ENUM_LABEL_DEFERRED_MENU_SOUNDS_LIST;
case ACTION_OK_DL_MENU_FILE_BROWSER_SETTINGS_LIST:
return MENU_ENUM_LABEL_DEFERRED_MENU_FILE_BROWSER_SETTINGS_LIST;
case ACTION_OK_DL_RETRO_ACHIEVEMENTS_SETTINGS_LIST:
@ -289,6 +291,9 @@ int generic_action_ok_displaylist_push(const char *path,
file_list_t *menu_stack = menu_entries_get_menu_stack_ptr(0);
char *menu_driver = settings->arrays.menu_driver;
if (settings->bools.audio_enable_menu && settings->bools.audio_enable_menu_ok)
audio_driver_mixer_play_menu_sound(AUDIO_MIXER_SYSTEM_SLOT_OK);
menu_displaylist_info_init(&info);
info.list = menu_stack;
@ -869,6 +874,7 @@ int generic_action_ok_displaylist_push(const char *path,
case ACTION_OK_DL_QUICK_MENU_OVERRIDE_OPTIONS_LIST:
case ACTION_OK_DL_USER_INTERFACE_SETTINGS_LIST:
case ACTION_OK_DL_POWER_MANAGEMENT_SETTINGS_LIST:
case ACTION_OK_DL_MENU_SOUNDS_LIST:
case ACTION_OK_DL_MENU_FILE_BROWSER_SETTINGS_LIST:
case ACTION_OK_DL_RETRO_ACHIEVEMENTS_SETTINGS_LIST:
case ACTION_OK_DL_UPDATER_SETTINGS_LIST:
@ -1249,6 +1255,11 @@ static int set_path_generic(const char *label, const char *action_path)
static int generic_action_ok_command(enum event_command cmd)
{
settings_t *settings = config_get_ptr();
if (settings->bools.audio_enable_menu && settings->bools.audio_enable_menu_ok)
audio_driver_mixer_play_menu_sound(AUDIO_MIXER_SYSTEM_SLOT_OK);
if (!command_event(cmd, NULL))
return menu_cbs_exit();
return 0;
@ -1321,6 +1332,10 @@ static int generic_action_ok(const char *path,
const char *menu_label = NULL;
const char *flush_char = NULL;
menu_handle_t *menu = NULL;
settings_t *settings = config_get_ptr();
if (settings->bools.audio_enable_menu && settings->bools.audio_enable_menu_ok)
audio_driver_mixer_play_menu_sound(AUDIO_MIXER_SYSTEM_SLOT_OK);
if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu))
goto error;
@ -3931,6 +3946,7 @@ default_action_ok_func(action_ok_quick_menu_override_options, ACTION_OK_DL_QUICK
default_action_ok_func(action_ok_menu_views_list, ACTION_OK_DL_MENU_VIEWS_SETTINGS_LIST)
default_action_ok_func(action_ok_quick_menu_views_list, ACTION_OK_DL_QUICK_MENU_VIEWS_SETTINGS_LIST)
default_action_ok_func(action_ok_power_management_list, ACTION_OK_DL_POWER_MANAGEMENT_SETTINGS_LIST)
default_action_ok_func(action_ok_menu_sounds_list, ACTION_OK_DL_MENU_SOUNDS_LIST)
default_action_ok_func(action_ok_user_interface_list, ACTION_OK_DL_USER_INTERFACE_SETTINGS_LIST)
default_action_ok_func(action_ok_menu_file_browser_list, ACTION_OK_DL_MENU_FILE_BROWSER_SETTINGS_LIST)
default_action_ok_func(action_ok_retro_achievements_list, ACTION_OK_DL_RETRO_ACHIEVEMENTS_SETTINGS_LIST)
@ -5510,6 +5526,9 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs,
case MENU_ENUM_LABEL_POWER_MANAGEMENT_SETTINGS:
BIND_ACTION_OK(cbs, action_ok_power_management_list);
break;
case MENU_ENUM_LABEL_MENU_SOUNDS:
BIND_ACTION_OK(cbs, action_ok_menu_sounds_list);
break;
case MENU_ENUM_LABEL_MENU_FILE_BROWSER_SETTINGS:
BIND_ACTION_OK(cbs, action_ok_menu_file_browser_list);
break;

View File

@ -135,7 +135,8 @@ default_title_macro(action_get_menu_views_settings_list, MENU_ENUM_LABEL_
default_title_macro(action_get_quick_menu_views_settings_list, MENU_ENUM_LABEL_VALUE_QUICK_MENU_VIEWS_SETTINGS)
default_title_macro(action_get_menu_settings_list, MENU_ENUM_LABEL_VALUE_MENU_SETTINGS)
default_title_macro(action_get_user_interface_settings_list, MENU_ENUM_LABEL_VALUE_USER_INTERFACE_SETTINGS)
default_title_macro(action_get_power_management_settings_list, MENU_ENUM_LABEL_VALUE_POWER_MANAGEMENT_SETTINGS)
default_title_macro(action_get_power_management_settings_list, MENU_ENUM_LABEL_VALUE_POWER_MANAGEMENT_SETTINGS)
default_title_macro(action_get_menu_sounds_list, MENU_ENUM_LABEL_VALUE_MENU_SOUNDS)
default_title_macro(action_get_menu_file_browser_settings_list, MENU_ENUM_LABEL_VALUE_MENU_FILE_BROWSER_SETTINGS)
default_title_macro(action_get_retro_achievements_settings_list,MENU_ENUM_LABEL_VALUE_RETRO_ACHIEVEMENTS_SETTINGS)
default_title_macro(action_get_wifi_settings_list, MENU_ENUM_LABEL_VALUE_WIFI_SETTINGS)
@ -436,6 +437,11 @@ static int menu_cbs_init_bind_title_compare_label(menu_file_list_cbs_t *cbs,
BIND_ACTION_GET_TITLE(cbs, action_get_power_management_settings_list);
return 0;
}
else if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_MENU_SOUNDS_LIST)))
{
BIND_ACTION_GET_TITLE(cbs, action_get_menu_sounds_list);
return 0;
}
else if (string_is_equal(label, msg_hash_to_str(MENU_ENUM_LABEL_DEFERRED_MENU_FILE_BROWSER_SETTINGS_LIST)))
{
BIND_ACTION_GET_TITLE(cbs, action_get_menu_file_browser_settings_list);

View File

@ -129,6 +129,7 @@ enum
ACTION_OK_DL_MENU_SETTINGS_LIST,
ACTION_OK_DL_USER_INTERFACE_SETTINGS_LIST,
ACTION_OK_DL_POWER_MANAGEMENT_SETTINGS_LIST,
ACTION_OK_DL_MENU_SOUNDS_LIST,
ACTION_OK_DL_MENU_FILE_BROWSER_SETTINGS_LIST,
ACTION_OK_DL_RETRO_ACHIEVEMENTS_SETTINGS_LIST,
ACTION_OK_DL_UPDATER_SETTINGS_LIST,

View File

@ -6149,6 +6149,44 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist
MENU_ENUM_LABEL_NO_SETTINGS_FOUND,
0, 0, 0);
info->need_refresh = true;
info->need_push = true;
break;
case DISPLAYLIST_MENU_SOUNDS_LIST:
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_AUDIO_ENABLE_MENU,
PARSE_ONLY_BOOL, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_MENU_SOUND_OK,
PARSE_ONLY_BOOL, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_MENU_SOUND_CANCEL,
PARSE_ONLY_BOOL, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_MENU_SOUND_NOTICE,
PARSE_ONLY_BOOL, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_MENU_SOUND_BGM,
PARSE_ONLY_BOOL, false) == 0)
count++;
if (count == 0)
menu_entries_append_enum(info->list,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_SETTINGS_FOUND),
msg_hash_to_str(MENU_ENUM_LABEL_NO_SETTINGS_FOUND),
MENU_ENUM_LABEL_NO_SETTINGS_FOUND,
0, 0, 0);
info->need_refresh = true;
info->need_push = true;
break;
@ -6847,17 +6885,17 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, menu_displaylist
case DISPLAYLIST_AUDIO_SETTINGS_LIST:
menu_entries_ctl(MENU_ENTRIES_CTL_CLEAR, info->list);
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_MIDI_SETTINGS, PARSE_ACTION, false) == 0)
MENU_ENUM_LABEL_MIDI_SETTINGS, PARSE_ACTION, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_AUDIO_MIXER_SETTINGS, PARSE_ACTION, false) == 0)
count++;
if (menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_MENU_SOUNDS, PARSE_ACTION, false) == 0)
count++;
menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_AUDIO_ENABLE,
PARSE_ONLY_BOOL, false);
menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_AUDIO_ENABLE_MENU,
PARSE_ONLY_BOOL, false);
menu_displaylist_parse_settings_enum(menu, info,
MENU_ENUM_LABEL_AUDIO_MUTE,
PARSE_ONLY_BOOL, false);

View File

@ -143,6 +143,7 @@ enum menu_displaylist_ctl_state
DISPLAYLIST_MENU_SETTINGS_LIST,
DISPLAYLIST_USER_INTERFACE_SETTINGS_LIST,
DISPLAYLIST_POWER_MANAGEMENT_SETTINGS_LIST,
DISPLAYLIST_MENU_SOUNDS_LIST,
DISPLAYLIST_RETRO_ACHIEVEMENTS_SETTINGS_LIST,
DISPLAYLIST_UPDATER_SETTINGS_LIST,
DISPLAYLIST_WIFI_SETTINGS_LIST,

View File

@ -1847,6 +1847,9 @@ static void menu_driver_toggle(bool on)
if (pause_libretro && !enable_menu_sound)
command_event(CMD_EVENT_AUDIO_STOP, NULL);
/*if (settings->bools.audio_enable_menu && settings->bools.audio_enable_menu_bgm)
audio_driver_mixer_play_menu_sound_looped(AUDIO_MIXER_SYSTEM_SLOT_BGM);*/
/* Override keyboard callback to redirect to menu instead.
* We'll use this later for something ... */
@ -1873,6 +1876,9 @@ static void menu_driver_toggle(bool on)
if (pause_libretro && !enable_menu_sound)
command_event(CMD_EVENT_AUDIO_START, NULL);
/*if (settings->bools.audio_enable_menu && settings->bools.audio_enable_menu_bgm)
audio_driver_mixer_stop_stream(AUDIO_MIXER_SYSTEM_SLOT_BGM);*/
/* Restore libretro keyboard callback. */
if (key_event && frontend_key_event)
*key_event = *frontend_key_event;

View File

@ -122,6 +122,7 @@ enum settings_list_type
SETTINGS_LIST_MULTIMEDIA,
SETTINGS_LIST_USER_INTERFACE,
SETTINGS_LIST_POWER_MANAGEMENT,
SETTINGS_LIST_MENU_SOUNDS,
SETTINGS_LIST_PLAYLIST,
SETTINGS_LIST_CHEEVOS,
SETTINGS_LIST_CORE_UPDATER,
@ -3139,6 +3140,21 @@ void general_write_handler(rarch_setting_t *setting)
retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_NETPLAY_CHECK_FRAMES, NULL);
#endif
break;
case MENU_ENUM_LABEL_AUDIO_ENABLE_MENU:
if (settings->bools.audio_enable_menu)
audio_driver_load_menu_sounds();
else
audio_driver_mixer_stop_stream(AUDIO_MIXER_SYSTEM_SLOT_BGM);
break;
case MENU_ENUM_LABEL_MENU_SOUND_BGM:
if (settings->bools.audio_enable_menu)
{
if (settings->bools.audio_enable_menu_bgm)
audio_driver_mixer_play_menu_sound_looped(AUDIO_MIXER_SYSTEM_SLOT_BGM);
else
audio_driver_mixer_stop_stream(AUDIO_MIXER_SYSTEM_SLOT_BGM);
}
break;
case MENU_ENUM_LABEL_VIDEO_WINDOW_OPACITY:
video_display_server_set_window_opacity(settings->uints.video_window_opacity);
break;
@ -4068,6 +4084,14 @@ static bool setting_append_list(
parent_group);
settings_data_list_current_add_flags(list, list_info, SD_FLAG_LAKKA_ADVANCED);
CONFIG_ACTION(
list, list_info,
MENU_ENUM_LABEL_MENU_SOUNDS,
MENU_ENUM_LABEL_VALUE_MENU_SOUNDS,
&group_info,
&subgroup_info,
parent_group);
CONFIG_ACTION(
list, list_info,
MENU_ENUM_LABEL_INPUT_SETTINGS,
@ -6191,6 +6215,97 @@ static bool setting_append_list(
SD_FLAG_NONE
);
END_SUB_GROUP(list, list_info, parent_group);
END_GROUP(list, list_info, parent_group);
break;
case SETTINGS_LIST_MENU_SOUNDS:
START_GROUP(list, list_info, &group_info,
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_MENU_SOUNDS),
parent_group);
parent_group = msg_hash_to_str(MENU_ENUM_LABEL_AUDIO_SETTINGS);
START_SUB_GROUP(list, list_info, "State", &group_info, &subgroup_info, parent_group);
CONFIG_BOOL(
list, list_info,
&settings->bools.audio_enable_menu,
MENU_ENUM_LABEL_AUDIO_ENABLE_MENU,
MENU_ENUM_LABEL_VALUE_AUDIO_ENABLE_MENU,
audio_enable_menu,
MENU_ENUM_LABEL_VALUE_OFF,
MENU_ENUM_LABEL_VALUE_ON,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler,
SD_FLAG_NONE
);
CONFIG_BOOL(
list, list_info,
&settings->bools.audio_enable_menu_ok,
MENU_ENUM_LABEL_MENU_SOUND_OK,
MENU_ENUM_LABEL_VALUE_MENU_SOUND_OK,
audio_enable_menu_ok,
MENU_ENUM_LABEL_VALUE_OFF,
MENU_ENUM_LABEL_VALUE_ON,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler,
SD_FLAG_NONE
);
CONFIG_BOOL(
list, list_info,
&settings->bools.audio_enable_menu_cancel,
MENU_ENUM_LABEL_MENU_SOUND_CANCEL,
MENU_ENUM_LABEL_VALUE_MENU_SOUND_CANCEL,
audio_enable_menu_cancel,
MENU_ENUM_LABEL_VALUE_OFF,
MENU_ENUM_LABEL_VALUE_ON,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler,
SD_FLAG_NONE
);
CONFIG_BOOL(
list, list_info,
&settings->bools.audio_enable_menu_notice,
MENU_ENUM_LABEL_MENU_SOUND_NOTICE,
MENU_ENUM_LABEL_VALUE_MENU_SOUND_NOTICE,
audio_enable_menu_notice,
MENU_ENUM_LABEL_VALUE_OFF,
MENU_ENUM_LABEL_VALUE_ON,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler,
SD_FLAG_NONE
);
CONFIG_BOOL(
list, list_info,
&settings->bools.audio_enable_menu_bgm,
MENU_ENUM_LABEL_MENU_SOUND_BGM,
MENU_ENUM_LABEL_VALUE_MENU_SOUND_BGM,
audio_enable_menu_bgm,
MENU_ENUM_LABEL_VALUE_OFF,
MENU_ENUM_LABEL_VALUE_ON,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler,
SD_FLAG_NONE
);
END_SUB_GROUP(list, list_info, parent_group);
END_GROUP(list, list_info, parent_group);
break;
@ -6219,22 +6334,6 @@ static bool setting_append_list(
SD_FLAG_NONE
);
CONFIG_BOOL(
list, list_info,
&settings->bools.audio_enable_menu,
MENU_ENUM_LABEL_AUDIO_ENABLE_MENU,
MENU_ENUM_LABEL_VALUE_AUDIO_ENABLE_MENU,
false,
MENU_ENUM_LABEL_VALUE_OFF,
MENU_ENUM_LABEL_VALUE_ON,
&group_info,
&subgroup_info,
parent_group,
general_write_handler,
general_read_handler,
SD_FLAG_NONE
);
CONFIG_BOOL(
list, list_info,
audio_get_bool_ptr(AUDIO_ACTION_MUTE_ENABLE),
@ -11041,6 +11140,7 @@ static rarch_setting_t *menu_setting_new_internal(rarch_setting_info_t *list_inf
SETTINGS_LIST_MULTIMEDIA,
SETTINGS_LIST_USER_INTERFACE,
SETTINGS_LIST_POWER_MANAGEMENT,
SETTINGS_LIST_MENU_SOUNDS,
SETTINGS_LIST_PLAYLIST,
SETTINGS_LIST_CHEEVOS,
SETTINGS_LIST_CORE_UPDATER,

View File

@ -1129,6 +1129,7 @@ enum msg_hash_enums
MENU_ENUM_LABEL_DEFERRED_MENU_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_USER_INTERFACE_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_POWER_MANAGEMENT_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_MENU_SOUNDS_LIST,
MENU_ENUM_LABEL_DEFERRED_MENU_FILE_BROWSER_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_RETRO_ACHIEVEMENTS_SETTINGS_LIST,
MENU_ENUM_LABEL_DEFERRED_UPDATER_SETTINGS_LIST,
@ -2241,6 +2242,11 @@ enum msg_hash_enums
MENU_ENUM_LABEL_VALUE_HOLD_START,
MENU_LABEL(PLAYLIST_USE_OLD_FORMAT),
MENU_LABEL(MENU_SOUNDS),
MENU_LABEL(MENU_SOUND_OK),
MENU_LABEL(MENU_SOUND_CANCEL),
MENU_LABEL(MENU_SOUND_NOTICE),
MENU_LABEL(MENU_SOUND_BGM),
MSG_LAST
};

View File

@ -37,6 +37,10 @@
#include "../list_special.h"
#include "../paths.h"
#ifdef HAVE_THREADS
#include <rthreads/rthreads.h>
#endif
static const record_driver_t *record_drivers[] = {
#ifdef HAVE_FFMPEG
&record_ffmpeg,
@ -55,6 +59,43 @@ static bool streaming_enable = false;
static const record_driver_t *recording_driver = NULL;
void *recording_data = NULL;
#ifdef HAVE_THREADS
static slock_t *s_recording_driver_lock = NULL;
#endif
bool recording_driver_lock_inited(void)
{
return s_recording_driver_lock != NULL;
}
void recording_driver_lock_init(void)
{
s_recording_driver_lock = slock_new();
}
void recording_driver_lock_free(void)
{
if (s_recording_driver_lock)
slock_free(s_recording_driver_lock);
s_recording_driver_lock = NULL;
}
void recording_driver_lock(void)
{
#ifdef HAVE_THREADS
if (s_recording_driver_lock)
slock_lock(s_recording_driver_lock);
#endif
}
void recording_driver_unlock(void)
{
#ifdef HAVE_THREADS
if (s_recording_driver_lock)
slock_unlock(s_recording_driver_lock);
#endif
}
/**
* record_driver_find_ident:
* @idx : index of driver to get handle to.

View File

@ -214,6 +214,16 @@ bool streaming_is_enabled(void);
void recording_driver_update_streaming_url(void);
bool recording_driver_lock_inited(void);
void recording_driver_lock_init(void);
void recording_driver_lock(void);
void recording_driver_unlock(void);
void recording_driver_lock_free(void);
extern void *recording_data;
RETRO_END_DECLS

View File

@ -1404,6 +1404,10 @@ bool retroarch_main_init(int argc, char *argv[])
}
}
if (recording_driver_lock_inited())
recording_driver_lock_free();
recording_driver_lock_init();
command_event(CMD_EVENT_CHEATS_INIT, NULL);
drivers_init(DRIVERS_CMD_ALL);
command_event(CMD_EVENT_COMMAND_INIT, NULL);
@ -1434,6 +1438,15 @@ bool retroarch_main_init(int argc, char *argv[])
}
#endif
#ifdef HAVE_MENU
{
settings_t *settings = config_get_ptr();
if (settings->bools.audio_enable_menu)
audio_driver_load_menu_sounds();
}
#endif
return true;
error:
@ -1454,34 +1467,42 @@ bool retroarch_is_on_main_thread(void)
void rarch_menu_running(void)
{
settings_t *settings = config_get_ptr();
(void)settings;
#ifdef HAVE_MENU
menu_driver_ctl(RARCH_MENU_CTL_SET_TOGGLE, NULL);
/* Prevent stray input */
input_driver_set_flushing_input();
if (settings && settings->bools.audio_enable_menu && settings->bools.audio_enable_menu_bgm)
audio_driver_mixer_play_menu_sound_looped(AUDIO_MIXER_SYSTEM_SLOT_BGM);
#endif
#ifdef HAVE_OVERLAY
{
settings_t *settings = config_get_ptr();
if (settings && settings->bools.input_overlay_hide_in_menu)
command_event(CMD_EVENT_OVERLAY_DEINIT, NULL);
}
if (settings && settings->bools.input_overlay_hide_in_menu)
command_event(CMD_EVENT_OVERLAY_DEINIT, NULL);
#endif
}
void rarch_menu_running_finished(void)
{
settings_t *settings = config_get_ptr();
(void)settings;
#ifdef HAVE_MENU
menu_driver_ctl(RARCH_MENU_CTL_UNSET_TOGGLE, NULL);
/* Prevent stray input */
input_driver_set_flushing_input();
if (settings && settings->bools.audio_enable_menu && settings->bools.audio_enable_menu_bgm)
audio_driver_mixer_stop_stream(AUDIO_MIXER_SYSTEM_SLOT_BGM);
#endif
video_driver_set_texture_enable(false, false);
#ifdef HAVE_OVERLAY
{
settings_t *settings = config_get_ptr();
if (settings && settings->bools.input_overlay_hide_in_menu)
command_event(CMD_EVENT_OVERLAY_INIT, NULL);
}
if (settings && settings->bools.input_overlay_hide_in_menu)
command_event(CMD_EVENT_OVERLAY_INIT, NULL);
#endif
}

View File

@ -284,6 +284,13 @@
# Enable audio.
# audio_enable = true
# Enable menu audio sounds.
# audio_enable_menu = false
# audio_enable_menu_ok = false
# audio_enable_menu_cancel = false
# audio_enable_menu_notice = false
# audio_enable_menu_bgm = false
# Mutes audio.
# audio_mute_enable = false

View File

@ -56,6 +56,7 @@ struct audio_mixer_handle
bool is_finished;
enum audio_mixer_type type;
char path[4095];
retro_task_callback_t cb;
};
static void task_audio_mixer_load_free(retro_task_t *task)
@ -71,6 +72,9 @@ static void task_audio_mixer_load_free(retro_task_t *task)
free(mixer->buffer->path);
free(mixer->buffer);
}
if (mixer->cb)
mixer->cb(NULL, NULL, NULL);
}
if (!string_is_empty(nbio->path))
@ -574,6 +578,7 @@ bool task_push_audio_mixer_load(
goto error;
mixer->is_finished = false;
mixer->cb = cb;
strlcpy(mixer->path, fullpath, sizeof(mixer->path));