diff --git a/audio/audio_driver.c b/audio/audio_driver.c index 9293ddcaa4..87fdb76df7 100644 --- a/audio/audio_driver.c +++ b/audio/audio_driver.c @@ -1143,17 +1143,15 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params) } if (params->state == AUDIO_STREAM_STATE_PLAYING) - { voice = audio_mixer_play(handle, looped, params->volume, stop_cb); - audio_mixer_active = true; - } else if (params->state == AUDIO_STREAM_STATE_PLAYING_LOOPED) { looped = true; voice = audio_mixer_play(handle, looped, params->volume, stop_cb); - audio_mixer_active = true; } + audio_mixer_active = true; + 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; diff --git a/menu/cbs/menu_cbs_ok.c b/menu/cbs/menu_cbs_ok.c index fea7c4a36b..c232025db6 100644 --- a/menu/cbs/menu_cbs_ok.c +++ b/menu/cbs/menu_cbs_ok.c @@ -1868,6 +1868,25 @@ static int action_ok_audio_add_to_mixer(const char *path, return 0; } +static int action_ok_audio_add_to_mixer_and_play(const char *path, + const char *label, unsigned type, size_t idx, size_t entry_idx) +{ + const char *entry_path = NULL; + playlist_t *tmp_playlist = playlist_get_cached(); + + if (!tmp_playlist) + return -1; + + playlist_get_index(tmp_playlist, entry_idx, + &entry_path, NULL, NULL, NULL, NULL, NULL); + + if (filestream_exists(entry_path)) + task_push_audio_mixer_load_and_play(entry_path, + NULL, NULL); + + return 0; +} + static int action_ok_audio_add_to_mixer_and_collection(const char *path, const char *label, unsigned type, size_t idx, size_t entry_idx) { @@ -1890,7 +1909,7 @@ static int action_ok_audio_add_to_mixer_and_collection(const char *path, "musicplayer"); if (filestream_exists(combined_path)) - task_push_audio_mixer_load(combined_path, + task_push_audio_mixer_load_and_play(combined_path, NULL, NULL); return 0; @@ -4143,6 +4162,9 @@ static int menu_cbs_init_bind_ok_compare_label(menu_file_list_cbs_t *cbs, case MENU_ENUM_LABEL_ADD_TO_MIXER: BIND_ACTION_OK(cbs, action_ok_audio_add_to_mixer); break; + case MENU_ENUM_LABEL_ADD_TO_MIXER_AND_PLAY: + BIND_ACTION_OK(cbs, action_ok_audio_add_to_mixer_and_play); + break; case MENU_ENUM_LABEL_MENU_WALLPAPER: BIND_ACTION_OK(cbs, action_ok_menu_wallpaper); break; diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 7d1e643ba7..6b9c1ce9c7 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -2841,6 +2841,12 @@ static int menu_displaylist_parse_horizontal_content_actions( msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_MIXER), MENU_ENUM_LABEL_ADD_TO_MIXER, FILE_TYPE_PLAYLIST_ENTRY, 0, idx); + + menu_entries_append_enum(info->list, + msg_hash_to_str(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER_AND_PLAY), + msg_hash_to_str(MENU_ENUM_LABEL_ADD_TO_MIXER_AND_PLAY), + MENU_ENUM_LABEL_ADD_TO_MIXER_AND_PLAY, + FILE_TYPE_PLAYLIST_ENTRY, 0, idx); } menu_entries_append_enum(info->list, diff --git a/tasks/task_audio_mixer.c b/tasks/task_audio_mixer.c index 2943504e9d..833412fd78 100644 --- a/tasks/task_audio_mixer.c +++ b/tasks/task_audio_mixer.c @@ -98,6 +98,31 @@ static void task_audio_mixer_handle_upload_ogg(void *task_data, audio_mixer_stream_params_t params; nbio_buf_t *img = (nbio_buf_t*)task_data; + if (!img) + return; + + params.volume = 1.0f; + params.type = AUDIO_MIXER_TYPE_OGG; + params.state = AUDIO_STREAM_STATE_STOPPED; + params.buf = img->buf; + params.bufsize = img->bufsize; + params.cb = NULL; + params.basename = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL; + + audio_driver_mixer_add_stream(¶ms); + + if (params.basename != NULL) + free(params.basename); + free(img); + free(user_data); +} + +static void task_audio_mixer_handle_upload_ogg_and_play(void *task_data, + void *user_data, const char *err) +{ + audio_mixer_stream_params_t params; + nbio_buf_t *img = (nbio_buf_t*)task_data; + if (!img) return; @@ -123,6 +148,31 @@ static void task_audio_mixer_handle_upload_flac(void *task_data, audio_mixer_stream_params_t params; nbio_buf_t *img = (nbio_buf_t*)task_data; + if (!img) + return; + + params.volume = 1.0f; + params.type = AUDIO_MIXER_TYPE_FLAC; + params.state = AUDIO_STREAM_STATE_STOPPED; + params.buf = img->buf; + params.bufsize = img->bufsize; + params.cb = NULL; + params.basename = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL; + + audio_driver_mixer_add_stream(¶ms); + + if (params.basename != NULL) + free(params.basename); + free(img); + free(user_data); +} + +static void task_audio_mixer_handle_upload_flac_and_play(void *task_data, + void *user_data, const char *err) +{ + audio_mixer_stream_params_t params; + nbio_buf_t *img = (nbio_buf_t*)task_data; + if (!img) return; @@ -148,6 +198,31 @@ static void task_audio_mixer_handle_upload_mp3(void *task_data, audio_mixer_stream_params_t params; nbio_buf_t *img = (nbio_buf_t*)task_data; + if (!img) + return; + + params.volume = 1.0f; + params.type = AUDIO_MIXER_TYPE_MP3; + params.state = AUDIO_STREAM_STATE_STOPPED; + params.buf = img->buf; + params.bufsize = img->bufsize; + params.cb = NULL; + params.basename = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL; + + audio_driver_mixer_add_stream(¶ms); + + if (params.basename != NULL) + free(params.basename); + free(img); + free(user_data); +} + +static void task_audio_mixer_handle_upload_mp3_and_play(void *task_data, + void *user_data, const char *err) +{ + audio_mixer_stream_params_t params; + nbio_buf_t *img = (nbio_buf_t*)task_data; + if (!img) return; @@ -173,6 +248,31 @@ static void task_audio_mixer_handle_upload_mod(void *task_data, audio_mixer_stream_params_t params; nbio_buf_t *img = (nbio_buf_t*)task_data; + if (!img) + return; + + params.volume = 1.0f; + params.type = AUDIO_MIXER_TYPE_MOD; + params.state = AUDIO_STREAM_STATE_STOPPED; + params.buf = img->buf; + params.bufsize = img->bufsize; + params.cb = NULL; + params.basename = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL; + + audio_driver_mixer_add_stream(¶ms); + + if (params.basename != NULL) + free(params.basename); + free(img); + free(user_data); +} + +static void task_audio_mixer_handle_upload_mod_and_play(void *task_data, + void *user_data, const char *err) +{ + audio_mixer_stream_params_t params; + nbio_buf_t *img = (nbio_buf_t*)task_data; + if (!img) return; @@ -198,6 +298,31 @@ static void task_audio_mixer_handle_upload_wav(void *task_data, audio_mixer_stream_params_t params; nbio_buf_t *img = (nbio_buf_t*)task_data; + if (!img) + return; + + params.volume = 1.0f; + params.type = AUDIO_MIXER_TYPE_WAV; + params.state = AUDIO_STREAM_STATE_STOPPED; + params.buf = img->buf; + params.bufsize = img->bufsize; + params.cb = NULL; + params.basename = !string_is_empty(img->path) ? strdup(path_basename(img->path)) : NULL; + + audio_driver_mixer_add_stream(¶ms); + + if (params.basename != NULL) + free(params.basename); + free(img); + free(user_data); +} + +static void task_audio_mixer_handle_upload_wav_and_play(void *task_data, + void *user_data, const char *err) +{ + audio_mixer_stream_params_t params; + nbio_buf_t *img = (nbio_buf_t*)task_data; + if (!img) return; @@ -249,6 +374,99 @@ bool task_audio_mixer_load_handler(retro_task_t *task) return true; } +bool task_push_audio_mixer_load_and_play(const char *fullpath, retro_task_callback_t cb, void *user_data) +{ + nbio_handle_t *nbio = NULL; + struct audio_mixer_handle *image = NULL; + retro_task_t *t = (retro_task_t*)calloc(1, sizeof(*t)); + + if (!t) + goto error; + + nbio = (nbio_handle_t*)calloc(1, sizeof(*nbio)); + + if (!nbio) + goto error; + + nbio->path = strdup(fullpath); + + image = (struct audio_mixer_handle*)calloc(1, sizeof(*image)); + if (!image) + goto error; + + image->is_finished = false; + + strlcpy(image->path, fullpath, sizeof(image->path)); + + nbio->type = NBIO_TYPE_NONE; + image->type = AUDIO_MIXER_TYPE_NONE; + + if (strstr(fullpath, file_path_str(FILE_PATH_WAV_EXTENSION))) + { + image->type = AUDIO_MIXER_TYPE_WAV; + nbio->type = NBIO_TYPE_WAV; + t->callback = task_audio_mixer_handle_upload_wav_and_play; + } + else if (strstr(fullpath, file_path_str(FILE_PATH_OGG_EXTENSION))) + { + image->type = AUDIO_MIXER_TYPE_OGG; + nbio->type = NBIO_TYPE_OGG; + t->callback = task_audio_mixer_handle_upload_ogg_and_play; + } + else if (strstr(fullpath, file_path_str(FILE_PATH_MP3_EXTENSION))) + { + image->type = AUDIO_MIXER_TYPE_MP3; + nbio->type = NBIO_TYPE_MP3; + t->callback = task_audio_mixer_handle_upload_mp3_and_play; + } + else if (strstr(fullpath, file_path_str(FILE_PATH_FLAC_EXTENSION))) + { + image->type = AUDIO_MIXER_TYPE_FLAC; + nbio->type = NBIO_TYPE_FLAC; + t->callback = task_audio_mixer_handle_upload_flac_and_play; + } + else if ( strstr(fullpath, file_path_str(FILE_PATH_MOD_EXTENSION)) || + strstr(fullpath, file_path_str(FILE_PATH_S3M_EXTENSION)) || + strstr(fullpath, file_path_str(FILE_PATH_XM_EXTENSION))) + { + image->type = AUDIO_MIXER_TYPE_MOD; + nbio->type = NBIO_TYPE_MOD; + t->callback = task_audio_mixer_handle_upload_mod_and_play; + } + + nbio->data = (struct audio_mixer_handle*)image; + nbio->is_finished = false; + nbio->cb = &cb_nbio_audio_mixer_load; + nbio->status = NBIO_STATUS_INIT; + + t->state = nbio; + t->handler = task_file_load_handler; + t->cleanup = task_audio_mixer_load_free; + t->user_data = user_data; + + task_queue_push(t); + + return true; + +error: + if (nbio) + { + if (!string_is_empty(nbio->path)) + free(nbio->path); + if (nbio->data) + free(nbio->data); + nbio_free(nbio->handle); + free(nbio); + } + if (t) + free(t); + + RARCH_ERR("[audio mixer load] Failed to open '%s': %s.\n", + fullpath, strerror(errno)); + + return false; +} + bool task_push_audio_mixer_load(const char *fullpath, retro_task_callback_t cb, void *user_data) { nbio_handle_t *nbio = NULL; diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h index 1e04454e14..fe9bd41122 100644 --- a/tasks/tasks_internal.h +++ b/tasks/tasks_internal.h @@ -259,7 +259,11 @@ void task_push_get_powerstate(void); enum frontend_powerstate get_last_powerstate(int *percent); -bool task_push_audio_mixer_load(const char *fullpath, retro_task_callback_t cb, void *user_data); +bool task_push_audio_mixer_load_and_play( + const char *fullpath, retro_task_callback_t cb, void *user_data); + +bool task_push_audio_mixer_load( + const char *fullpath, retro_task_callback_t cb, void *user_data); extern const char* const input_builtin_autoconfs[];