(Audio mixer) Add Sequential playback mode

This commit is contained in:
twinaphex 2018-05-02 21:43:16 +02:00
parent b480cdbe26
commit ab360ae3ac
6 changed files with 120 additions and 8 deletions

View File

@ -179,6 +179,11 @@ static void *audio_driver_context_audio_data = NULL;
static bool audio_suspended = false; static bool audio_suspended = false;
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);
enum resampler_quality audio_driver_get_resampler_quality(void) enum resampler_quality audio_driver_get_resampler_quality(void)
{ {
settings_t *settings = config_get_ptr(); settings_t *settings = config_get_ptr();
@ -1077,6 +1082,50 @@ static void audio_mixer_play_stop_cb(
} }
} }
static void audio_mixer_play_stop_sequential_cb(
audio_mixer_sound_t *sound, unsigned reason)
{
int idx = audio_mixer_find_index(sound);
switch (reason)
{
case AUDIO_MIXER_SOUND_FINISHED:
audio_mixer_destroy(sound);
if (idx >= 0)
{
unsigned i = (unsigned)idx;
if (!string_is_empty(audio_mixer_streams[i].name))
free(audio_mixer_streams[i].name);
audio_mixer_streams[i].name = NULL;
audio_mixer_streams[i].state = AUDIO_STREAM_STATE_NONE;
audio_mixer_streams[i].volume = 0.0f;
audio_mixer_streams[i].buf = NULL;
audio_mixer_streams[i].stop_cb = NULL;
audio_mixer_streams[i].handle = NULL;
audio_mixer_streams[i].voice = NULL;
i++;
for (; i < AUDIO_MIXER_MAX_STREAMS; i++)
{
if (audio_mixer_streams[i].state == AUDIO_STREAM_STATE_STOPPED)
{
audio_driver_mixer_play_stream_sequential(i);
break;
}
}
}
break;
case AUDIO_MIXER_SOUND_STOPPED:
break;
case AUDIO_MIXER_SOUND_REPEATED:
break;
}
}
bool audio_driver_mixer_get_free_stream_slot(unsigned *id) bool audio_driver_mixer_get_free_stream_slot(unsigned *id)
{ {
unsigned i; unsigned i;
@ -1149,10 +1198,15 @@ bool audio_driver_mixer_add_stream(audio_mixer_stream_params_t *params)
{ {
case AUDIO_STREAM_STATE_PLAYING_LOOPED: case AUDIO_STREAM_STATE_PLAYING_LOOPED:
looped = true; looped = true;
/* fall-through */ voice = audio_mixer_play(handle, looped, params->volume, stop_cb);
break;
case AUDIO_STREAM_STATE_PLAYING: case AUDIO_STREAM_STATE_PLAYING:
voice = audio_mixer_play(handle, looped, params->volume, stop_cb); voice = audio_mixer_play(handle, looped, params->volume, stop_cb);
break; break;
case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
stop_cb = audio_mixer_play_stop_sequential_cb;
voice = audio_mixer_play(handle, looped, params->volume, stop_cb);
break;
default: default:
break; break;
} }
@ -1178,7 +1232,7 @@ enum audio_mixer_state audio_driver_mixer_get_stream_state(unsigned i)
return audio_mixer_streams[i].state; return audio_mixer_streams[i].state;
} }
static void audio_driver_mixer_play_stream_internal(unsigned i, bool looped) static void audio_driver_mixer_play_stream_internal(unsigned i, unsigned type)
{ {
bool set_state = false; bool set_state = false;
@ -1188,27 +1242,38 @@ static void audio_driver_mixer_play_stream_internal(unsigned i, bool looped)
switch (audio_mixer_streams[i].state) switch (audio_mixer_streams[i].state)
{ {
case AUDIO_STREAM_STATE_STOPPED: case AUDIO_STREAM_STATE_STOPPED:
audio_mixer_streams[i].voice = audio_mixer_play(audio_mixer_streams[i].handle, looped, 1.0f, audio_mixer_streams[i].stop_cb); audio_mixer_streams[i].voice = audio_mixer_play(audio_mixer_streams[i].handle,
(type == AUDIO_STREAM_STATE_PLAYING_LOOPED) ? true : false,
1.0f, audio_mixer_streams[i].stop_cb);
set_state = true; set_state = true;
break; break;
case AUDIO_STREAM_STATE_PLAYING: case AUDIO_STREAM_STATE_PLAYING:
case AUDIO_STREAM_STATE_PLAYING_LOOPED: case AUDIO_STREAM_STATE_PLAYING_LOOPED:
case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
case AUDIO_STREAM_STATE_NONE: case AUDIO_STREAM_STATE_NONE:
break; break;
} }
if (set_state) if (set_state)
audio_mixer_streams[i].state = looped ? AUDIO_STREAM_STATE_PLAYING_LOOPED : AUDIO_STREAM_STATE_PLAYING; audio_mixer_streams[i].state = type;
} }
void audio_driver_mixer_play_stream(unsigned i) void audio_driver_mixer_play_stream(unsigned i)
{ {
audio_driver_mixer_play_stream_internal(i, false); 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_stream_looped(unsigned i) void audio_driver_mixer_play_stream_looped(unsigned i)
{ {
audio_driver_mixer_play_stream_internal(i, true); audio_mixer_streams[i].stop_cb = audio_mixer_play_stop_cb;
audio_driver_mixer_play_stream_internal(i, AUDIO_STREAM_STATE_PLAYING_LOOPED);
}
void audio_driver_mixer_play_stream_sequential(unsigned i)
{
audio_mixer_streams[i].stop_cb = audio_mixer_play_stop_sequential_cb;
audio_driver_mixer_play_stream_internal(i, AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL);
} }
float audio_driver_mixer_get_stream_volume(unsigned i) float audio_driver_mixer_get_stream_volume(unsigned i)
@ -1245,6 +1310,7 @@ void audio_driver_mixer_stop_stream(unsigned i)
{ {
case AUDIO_STREAM_STATE_PLAYING: case AUDIO_STREAM_STATE_PLAYING:
case AUDIO_STREAM_STATE_PLAYING_LOOPED: case AUDIO_STREAM_STATE_PLAYING_LOOPED:
case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
set_state = true; set_state = true;
break; break;
case AUDIO_STREAM_STATE_STOPPED: case AUDIO_STREAM_STATE_STOPPED:
@ -1274,6 +1340,7 @@ void audio_driver_mixer_remove_stream(unsigned i)
{ {
case AUDIO_STREAM_STATE_PLAYING: case AUDIO_STREAM_STATE_PLAYING:
case AUDIO_STREAM_STATE_PLAYING_LOOPED: case AUDIO_STREAM_STATE_PLAYING_LOOPED:
case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
audio_driver_mixer_stop_stream(i); audio_driver_mixer_stop_stream(i);
destroy = true; destroy = true;
break; break;

View File

@ -53,7 +53,8 @@ enum audio_mixer_state
AUDIO_STREAM_STATE_NONE = 0, AUDIO_STREAM_STATE_NONE = 0,
AUDIO_STREAM_STATE_STOPPED, AUDIO_STREAM_STATE_STOPPED,
AUDIO_STREAM_STATE_PLAYING, AUDIO_STREAM_STATE_PLAYING,
AUDIO_STREAM_STATE_PLAYING_LOOPED AUDIO_STREAM_STATE_PLAYING_LOOPED,
AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL
}; };
typedef struct audio_mixer_stream typedef struct audio_mixer_stream
@ -294,6 +295,8 @@ 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_stream(unsigned i);
void audio_driver_mixer_play_stream_sequential(unsigned i);
void audio_driver_mixer_play_stream_looped(unsigned i); void audio_driver_mixer_play_stream_looped(unsigned i);
void audio_driver_mixer_stop_stream(unsigned i); void audio_driver_mixer_stop_stream(unsigned i);

View File

@ -1780,6 +1780,7 @@ static int action_ok_mixer_stream_action_play(const char *path,
break; break;
case AUDIO_STREAM_STATE_PLAYING: case AUDIO_STREAM_STATE_PLAYING:
case AUDIO_STREAM_STATE_PLAYING_LOOPED: case AUDIO_STREAM_STATE_PLAYING_LOOPED:
case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
case AUDIO_STREAM_STATE_NONE: case AUDIO_STREAM_STATE_NONE:
break; break;
} }
@ -1799,6 +1800,27 @@ static int action_ok_mixer_stream_action_play_looped(const char *path,
break; break;
case AUDIO_STREAM_STATE_PLAYING: case AUDIO_STREAM_STATE_PLAYING:
case AUDIO_STREAM_STATE_PLAYING_LOOPED: case AUDIO_STREAM_STATE_PLAYING_LOOPED:
case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
case AUDIO_STREAM_STATE_NONE:
break;
}
return 0;
}
static int action_ok_mixer_stream_action_play_sequential(const char *path,
const char *label, unsigned type, size_t idx, size_t entry_idx)
{
unsigned stream_id = type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_SEQUENTIAL_BEGIN;
enum audio_mixer_state state = audio_driver_mixer_get_stream_state(stream_id);
switch (state)
{
case AUDIO_STREAM_STATE_STOPPED:
audio_driver_mixer_play_stream_sequential(stream_id);
break;
case AUDIO_STREAM_STATE_PLAYING:
case AUDIO_STREAM_STATE_PLAYING_LOOPED:
case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
case AUDIO_STREAM_STATE_NONE: case AUDIO_STREAM_STATE_NONE:
break; break;
} }
@ -1815,6 +1837,7 @@ static int action_ok_mixer_stream_action_remove(const char *path,
{ {
case AUDIO_STREAM_STATE_PLAYING: case AUDIO_STREAM_STATE_PLAYING:
case AUDIO_STREAM_STATE_PLAYING_LOOPED: case AUDIO_STREAM_STATE_PLAYING_LOOPED:
case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
case AUDIO_STREAM_STATE_STOPPED: case AUDIO_STREAM_STATE_STOPPED:
audio_driver_mixer_remove_stream(stream_id); audio_driver_mixer_remove_stream(stream_id);
break; break;
@ -1834,6 +1857,7 @@ static int action_ok_mixer_stream_action_stop(const char *path,
{ {
case AUDIO_STREAM_STATE_PLAYING: case AUDIO_STREAM_STATE_PLAYING:
case AUDIO_STREAM_STATE_PLAYING_LOOPED: case AUDIO_STREAM_STATE_PLAYING_LOOPED:
case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
audio_driver_mixer_stop_stream(stream_id); audio_driver_mixer_stop_stream(stream_id);
break; break;
case AUDIO_STREAM_STATE_STOPPED: case AUDIO_STREAM_STATE_STOPPED:
@ -4733,6 +4757,11 @@ static int menu_cbs_init_bind_ok_compare_type(menu_file_list_cbs_t *cbs,
{ {
BIND_ACTION_OK(cbs, action_ok_mixer_stream_action_play_looped); BIND_ACTION_OK(cbs, action_ok_mixer_stream_action_play_looped);
} }
else if (type >= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_SEQUENTIAL_BEGIN
&& type <= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_SEQUENTIAL_END)
{
BIND_ACTION_OK(cbs, action_ok_mixer_stream_action_play_sequential);
}
else if (type >= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_REMOVE_BEGIN else if (type >= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_REMOVE_BEGIN
&& type <= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_REMOVE_END) && type <= MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_REMOVE_END)
{ {

View File

@ -488,6 +488,9 @@ static int action_bind_sublabel_audio_mixer_stream(
case AUDIO_STREAM_STATE_PLAYING_LOOPED: case AUDIO_STREAM_STATE_PLAYING_LOOPED:
strlcpy(msg, "Playing (Looped)", sizeof(msg)); strlcpy(msg, "Playing (Looped)", sizeof(msg));
break; break;
case AUDIO_STREAM_STATE_PLAYING_SEQUENTIAL:
strlcpy(msg, "Playing (Sequential)", sizeof(msg));
break;
} }
snprintf(s, len, "State : %s | Volume: %.2f dB", msg, snprintf(s, len, "State : %s | Volume: %.2f dB", msg,

View File

@ -4277,19 +4277,21 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data)
{ {
char lbl_play[128]; char lbl_play[128];
char lbl_play_looped[128]; char lbl_play_looped[128];
char lbl_play_sequential[128];
char lbl_remove[128]; char lbl_remove[128];
char lbl_stop[128]; char lbl_stop[128];
char lbl_volume[128]; char lbl_volume[128];
unsigned id = info->type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_BEGIN; unsigned id = info->type - MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_BEGIN;
lbl_remove[0] = lbl_stop[0] = lbl_play[0] = lbl_play_looped[0] = '\0'; lbl_remove[0] = lbl_stop[0] = lbl_play[0] = lbl_play_looped[0] = '\0';
lbl_volume[0] = '\0'; lbl_volume[0] = lbl_play_sequential[0] = '\0';
snprintf(lbl_volume, sizeof(lbl_volume), "mixer_stream_%d_action_volume", id); snprintf(lbl_volume, sizeof(lbl_volume), "mixer_stream_%d_action_volume", id);
snprintf(lbl_stop, sizeof(lbl_stop), "mixer_stream_%d_action_stop", id); snprintf(lbl_stop, sizeof(lbl_stop), "mixer_stream_%d_action_stop", id);
snprintf(lbl_remove, sizeof(lbl_remove), "mixer_stream_%d_action_remove", id); snprintf(lbl_remove, sizeof(lbl_remove), "mixer_stream_%d_action_remove", id);
snprintf(lbl_play, sizeof(lbl_play), "mixer_stream_%d_action_play", id); snprintf(lbl_play, sizeof(lbl_play), "mixer_stream_%d_action_play", id);
snprintf(lbl_play_looped, sizeof(lbl_play_looped), "mixer_stream_%d_action_play_looped", id); snprintf(lbl_play_looped, sizeof(lbl_play_looped), "mixer_stream_%d_action_play_looped", id);
snprintf(lbl_play_sequential, sizeof(lbl_play_sequential), "mixer_stream_%d_action_play_sequential", id);
menu_entries_append_enum(info->list, menu_entries_append_enum(info->list,
"Play", "Play",
@ -4303,6 +4305,12 @@ bool menu_displaylist_ctl(enum menu_displaylist_ctl_state type, void *data)
MSG_UNKNOWN, MSG_UNKNOWN,
(MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_BEGIN + id), (MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_BEGIN + id),
0, 0); 0, 0);
menu_entries_append_enum(info->list,
"Play (Sequential)",
lbl_play_sequential,
MSG_UNKNOWN,
(MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_SEQUENTIAL_BEGIN + id),
0, 0);
menu_entries_append_enum(info->list, menu_entries_append_enum(info->list,
"Stop", "Stop",
lbl_stop, lbl_stop,

View File

@ -201,6 +201,8 @@ enum menu_settings_type
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_BEGIN + 7, MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_BEGIN + 7,
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_BEGIN, 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 + 7, MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_PLAY_LOOPED_BEGIN + 7,
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 + 7,
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN, MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN,
MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN + 7, MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_END = MENU_SETTINGS_AUDIO_MIXER_STREAM_ACTIONS_VOLUME_BEGIN + 7,
MENU_SETTINGS_BIND_BEGIN, MENU_SETTINGS_BIND_BEGIN,