Have mpegplayer use the mixer (the playback channel, since it's mutually exclusive to audio playback) so the clicks and skip beep can be used according to user settings. Introduce some system sound functions to make easier playing event sounds from various places and convert files calling 'beep_play' to use 'system_sound_play' and 'keyclick_click'. Event sound could be become themeable.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30130 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Michael Sevakis 2011-07-08 22:31:15 +00:00
parent f1a5a25dac
commit 5663e1cd0a
10 changed files with 149 additions and 48 deletions

View file

@ -203,9 +203,7 @@ static int get_action_worker(int context, int timeout,
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
/* Produce keyclick */ /* Produce keyclick */
if (global_settings.keyclick && !(button & BUTTON_REL)) keyclick_click(button);
if (!(button & BUTTON_REPEAT) || global_settings.keyclick_repeats)
beep_play(4000, KEYCLICK_DURATION, 2500*global_settings.keyclick);
#endif #endif
if ((context != last_context) && ((last_button & BUTTON_REL) == 0) if ((context != last_context) && ((last_button & BUTTON_REL) == 0)

View file

@ -577,8 +577,7 @@ static void play_hop(int direction)
else if (direction == 1 && step >= remaining) else if (direction == 1 && step >= remaining)
{ {
#if CONFIG_CODEC == SWCODEC #if CONFIG_CODEC == SWCODEC
if(global_settings.beep) system_sound_play(SOUND_TRACK_NO_MORE);
beep_play(1000, 150, 1500*global_settings.beep);
#endif #endif
return; return;
} }

View file

@ -1037,3 +1037,51 @@ enum current_activity get_current_activity(void)
return current_activity[current_activity_top?current_activity_top-1:0]; return current_activity[current_activity_top?current_activity_top-1:0];
} }
#if CONFIG_CODEC == SWCODEC
/* Play a standard sound */
void system_sound_play(enum system_sound sound)
{
static const struct beep_params
{
int *setting;
unsigned short frequency;
unsigned short duration;
unsigned short amplitude;
} beep_params[] =
{
[SOUND_KEYCLICK] =
{ &global_settings.keyclick,
4000, KEYCLICK_DURATION, 2500 },
[SOUND_TRACK_SKIP] =
{ &global_settings.beep,
2000, 100, 2500 },
[SOUND_TRACK_NO_MORE] =
{ &global_settings.beep,
1000, 100, 1500 },
};
const struct beep_params *params = &beep_params[sound];
if (*params->setting)
{
beep_play(params->frequency, params->duration,
params->amplitude * *params->setting);
}
}
/* Produce keyclick based upon button and global settings */
void keyclick_click(int button)
{
/* Settings filters */
if (global_settings.keyclick &&
(global_settings.keyclick_repeats || !(button & BUTTON_REPEAT)))
{
/* Button filters */
if (button != BUTTON_NONE && !(button & BUTTON_REL)
&& !(button & (SYS_EVENT|BUTTON_MULTIMEDIA)) )
{
system_sound_play(SOUND_KEYCLICK);
}
}
}
#endif /* CONFIG_CODEC == SWCODEC */

View file

@ -100,9 +100,6 @@ int clamp_value_wrap(int value, int max, int min);
#endif #endif
#endif #endif
void beep_play(unsigned int frequency, unsigned int duration,
unsigned int amplitude);
enum current_activity { enum current_activity {
ACTIVITY_UNKNOWN = 0, ACTIVITY_UNKNOWN = 0,
ACTIVITY_MAINMENU, ACTIVITY_MAINMENU,
@ -118,6 +115,25 @@ enum current_activity {
ACTIVITY_PITCHSCREEN, ACTIVITY_PITCHSCREEN,
ACTIVITY_OPTIONSELECT ACTIVITY_OPTIONSELECT
}; };
#if CONFIG_CODEC == SWCODEC
void beep_play(unsigned int frequency, unsigned int duration,
unsigned int amplitude);
enum system_sound
{
SOUND_KEYCLICK = 0,
SOUND_TRACK_SKIP,
SOUND_TRACK_NO_MORE,
};
/* Play a standard sound */
void system_sound_play(enum system_sound sound);
/* Produce keyclick based upon button and global settings */
void keyclick_click(int button);
#endif /* CONFIG_CODEC == SWCODEC */
void push_current_activity(enum current_activity screen); void push_current_activity(enum current_activity screen);
void pop_current_activity(void); void pop_current_activity(void);
enum current_activity get_current_activity(void); enum current_activity get_current_activity(void);

View file

@ -3352,8 +3352,7 @@ void audio_skip(int offset)
processed one */ processed one */
skip_offset = accum; skip_offset = accum;
if (global_settings.beep) system_sound_play(SOUND_TRACK_SKIP);
beep_play(2000, 100, 2500*global_settings.beep);
LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", offset); LOGFQUEUE("audio > audio Q_AUDIO_SKIP %d", offset);
@ -3373,8 +3372,7 @@ void audio_skip(int offset)
else else
{ {
/* No more tracks */ /* No more tracks */
if (global_settings.beep) system_sound_play(SOUND_TRACK_NO_MORE);
beep_play(1000, 100, 1500*global_settings.beep);
} }
id3_mutex_unlock(); id3_mutex_unlock();

View file

@ -782,6 +782,13 @@ static const struct plugin_api rockbox_api = {
mixer_channel_status, mixer_channel_status,
mixer_channel_get_buffer, mixer_channel_get_buffer,
mixer_channel_calculate_peaks, mixer_channel_calculate_peaks,
mixer_channel_play_data,
mixer_channel_play_pause,
mixer_channel_stop,
mixer_channel_set_amplitude,
mixer_channel_get_bytes_waiting,
system_sound_play,
keyclick_click,
#endif #endif
}; };

View file

@ -146,7 +146,7 @@ void* plugin_get_buffer(size_t *buffer_size);
#define PLUGIN_MAGIC 0x526F634B /* RocK */ #define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */ /* increase this every time the api struct changes */
#define PLUGIN_API_VERSION 207 #define PLUGIN_API_VERSION 208
/* update this to latest version if a change to the api struct breaks /* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any backwards compatibility (and please take the opportunity to sort in any
@ -913,6 +913,16 @@ struct plugin_api {
void * (*mixer_channel_get_buffer)(enum pcm_mixer_channel channel, int *count); void * (*mixer_channel_get_buffer)(enum pcm_mixer_channel channel, int *count);
void (*mixer_channel_calculate_peaks)(enum pcm_mixer_channel channel, void (*mixer_channel_calculate_peaks)(enum pcm_mixer_channel channel,
int *left, int *right); int *left, int *right);
void (*mixer_channel_play_data)(enum pcm_mixer_channel channel,
pcm_play_callback_type get_more,
unsigned char *start, size_t size);
void (*mixer_channel_play_pause)(enum pcm_mixer_channel channel, bool play);
void (*mixer_channel_stop)(enum pcm_mixer_channel channel);
void (*mixer_channel_set_amplitude)(enum pcm_mixer_channel channel,
unsigned int amplitude);
size_t (*mixer_channel_get_bytes_waiting)(enum pcm_mixer_channel channel);
void (*system_sound_play)(enum system_sound sound);
void (*keyclick_click)(int button);
#endif #endif
}; };

View file

@ -214,6 +214,10 @@ int mpeg_button_get(int timeout)
mpeg_sysevent_clear(); mpeg_sysevent_clear();
button = timeout == TIMEOUT_BLOCK ? rb->button_get(true) : button = timeout == TIMEOUT_BLOCK ? rb->button_get(true) :
rb->button_get_w_tmo(timeout); rb->button_get_w_tmo(timeout);
/* Produce keyclick */
rb->keyclick_click(button);
return mpeg_sysevent_callback(button, NULL); return mpeg_sysevent_callback(button, NULL);
} }

View file

@ -386,6 +386,7 @@ enum video_action
VIDEO_STOP = 0, VIDEO_STOP = 0,
VIDEO_PREV, VIDEO_PREV,
VIDEO_NEXT, VIDEO_NEXT,
VIDEO_ACTION_MANUAL = 0x8000, /* Flag that says user did it */
}; };
/* OSD status - same order as icon array */ /* OSD status - same order as icon array */
@ -2139,7 +2140,7 @@ static int button_loop(void)
/* Release within 3 seconds of start: skip to previous /* Release within 3 seconds of start: skip to previous
* file */ * file */
osd_stop(); osd_stop();
next_action = VIDEO_PREV; next_action = VIDEO_PREV | VIDEO_ACTION_MANUAL;
} }
} }
else if ((button & ~BUTTON_REPEAT) == old_button) { else if ((button & ~BUTTON_REPEAT) == old_button) {
@ -2169,7 +2170,7 @@ static int button_loop(void)
if ((old_button | BUTTON_REL) == button) { if ((old_button | BUTTON_REL) == button) {
/* If button has been released: skip to next file */ /* If button has been released: skip to next file */
osd_stop(); osd_stop();
next_action = VIDEO_NEXT; next_action = VIDEO_NEXT | VIDEO_ACTION_MANUAL;
} }
else if ((button & ~BUTTON_REPEAT) == old_button) { else if ((button & ~BUTTON_REPEAT) == old_button) {
button = osd_seek_btn(old_button); button = osd_seek_btn(old_button);
@ -2251,11 +2252,10 @@ enum plugin_status plugin_start(const void* parameter)
while (!quit) while (!quit)
{ {
int result;
init_settings(videofile); init_settings(videofile);
result = stream_open(videofile); int result = stream_open(videofile);
bool manual_skip = false;
if (result >= STREAM_OK) { if (result >= STREAM_OK) {
/* start menu */ /* start menu */
@ -2267,6 +2267,8 @@ enum plugin_status plugin_start(const void* parameter)
if (result != MPEG_START_QUIT) { if (result != MPEG_START_QUIT) {
/* Enter button loop and process UI */ /* Enter button loop and process UI */
next_action = button_loop(); next_action = button_loop();
manual_skip = next_action & VIDEO_ACTION_MANUAL;
next_action &= ~VIDEO_ACTION_MANUAL;
} }
stream_close(); stream_close();
@ -2341,6 +2343,13 @@ enum plugin_status plugin_start(const void* parameter)
sizeof(videofile)); sizeof(videofile));
/* quit after finished the last videofile */ /* quit after finished the last videofile */
quit = !get_videofile_says; quit = !get_videofile_says;
if (manual_skip)
{
rb->system_sound_play(get_videofile_says ?
SOUND_TRACK_SKIP : SOUND_TRACK_NO_MORE);
}
break; break;
} }
case VIDEO_PREV: case VIDEO_PREV:
@ -2348,6 +2357,13 @@ enum plugin_status plugin_start(const void* parameter)
get_videofile_says = get_videofile(VIDEO_PREV, videofile, get_videofile_says = get_videofile(VIDEO_PREV, videofile,
sizeof(videofile)); sizeof(videofile));
/* if there is no previous file, play the same videofile */ /* if there is no previous file, play the same videofile */
if (manual_skip)
{
rb->system_sound_play(get_videofile_says ?
SOUND_TRACK_SKIP : SOUND_TRACK_NO_MORE);
}
break; break;
} }
case VIDEO_STOP: case VIDEO_STOP:

View file

@ -23,6 +23,9 @@
#include "plugin.h" #include "plugin.h"
#include "mpegplayer.h" #include "mpegplayer.h"
/* PCM channel we're using */
#define MPEG_PCM_CHANNEL PCM_MIXER_CHAN_PLAYBACK
/* Pointers */ /* Pointers */
/* Start of buffer */ /* Start of buffer */
@ -217,24 +220,22 @@ bool pcm_output_empty(void)
/* Flushes the buffer - clock keeps counting */ /* Flushes the buffer - clock keeps counting */
void pcm_output_flush(void) void pcm_output_flush(void)
{ {
bool playing, paused;
rb->pcm_play_lock(); rb->pcm_play_lock();
playing = rb->pcm_is_playing(); enum channel_status status = rb->mixer_channel_status(MPEG_PCM_CHANNEL);
paused = rb->pcm_is_paused();
/* Stop PCM to clear current buffer */ /* Stop PCM to clear current buffer */
if (playing) if (status != CHANNEL_STOPPED)
rb->pcm_play_stop(); rb->mixer_channel_stop(MPEG_PCM_CHANNEL);
rb->pcm_play_unlock();
pcm_reset_buffer(); pcm_reset_buffer();
/* Restart if playing state was current */ /* Restart if playing state was current */
if (playing && !paused) if (status == CHANNEL_PLAYING)
rb->pcm_play_data(get_more, NULL, 0); rb->mixer_channel_play_data(MPEG_PCM_CHANNEL,
get_more, NULL, 0);
rb->pcm_play_unlock();
} }
/* Seek the reference clock to the specified time - next audio data ready to /* Seek the reference clock to the specified time - next audio data ready to
@ -264,10 +265,12 @@ uint32_t pcm_output_get_clock(void)
do do
{ {
time = clock_time; time = clock_time;
rem = rb->pcm_get_bytes_waiting() >> 2; rem = rb->mixer_channel_get_bytes_waiting(MPEG_PCM_CHANNEL) >> 2;
} }
while (UNLIKELY(time != clock_time || while (UNLIKELY(time != clock_time ||
(rem == 0 && rb->pcm_is_playing() && !rb->pcm_is_paused()))); (rem == 0 &&
rb->mixer_channel_status(MPEG_PCM_CHANNEL) == CHANNEL_PLAYING))
);
return time - rem; return time - rem;
@ -283,10 +286,12 @@ uint32_t pcm_output_get_ticks(uint32_t *start)
do do
{ {
tick = clock_tick; tick = clock_tick;
rem = rb->pcm_get_bytes_waiting() >> 2; rem = rb->mixer_channel_get_bytes_waiting(MPEG_PCM_CHANNEL) >> 2;
} }
while (UNLIKELY(tick != clock_tick || while (UNLIKELY(tick != clock_tick ||
(rem == 0 && rb->pcm_is_playing() && !rb->pcm_is_paused()))); (rem == 0 &&
rb->mixer_channel_status(MPEG_PCM_CHANNEL) == CHANNEL_PLAYING))
);
if (start) if (start)
*start = clock_start; *start = clock_start;
@ -299,16 +304,22 @@ void pcm_output_play_pause(bool play)
{ {
rb->pcm_play_lock(); rb->pcm_play_lock();
if (rb->pcm_is_playing()) if (rb->mixer_channel_status(MPEG_PCM_CHANNEL) != CHANNEL_STOPPED)
{ {
rb->pcm_play_pause(play); rb->mixer_channel_play_pause(MPEG_PCM_CHANNEL, play);
rb->pcm_play_unlock();
} }
else if (play) else
{ {
rb->pcm_play_data(get_more, NULL, 0); rb->pcm_play_unlock();
}
rb->pcm_play_unlock(); if (play)
{
rb->mixer_channel_set_amplitude(MPEG_PCM_CHANNEL, MIX_AMP_UNITY);
rb->mixer_channel_play_data(MPEG_PCM_CHANNEL,
get_more, NULL, 0);
}
}
} }
/* Stops all playback and resets the clock */ /* Stops all playback and resets the clock */
@ -316,13 +327,13 @@ void pcm_output_stop(void)
{ {
rb->pcm_play_lock(); rb->pcm_play_lock();
if (rb->pcm_is_playing()) if (rb->mixer_channel_status(MPEG_PCM_CHANNEL) != CHANNEL_STOPPED)
rb->pcm_play_stop(); rb->mixer_channel_stop(MPEG_PCM_CHANNEL);
rb->pcm_play_unlock();
pcm_output_flush(); pcm_output_flush();
pcm_output_set_clock(0); pcm_output_set_clock(0);
rb->pcm_play_unlock();
} }
/* Drains any data if the start threshold hasn't been reached */ /* Drains any data if the start threshold hasn't been reached */
@ -343,11 +354,6 @@ bool pcm_output_init(void)
pcm_reset_buffer(); pcm_reset_buffer();
/* Some targets could play at the movie frequency without resampling but
* as of now DSP assumes a certain frequency (always 44100Hz) so
* resampling will be needed for other movie audio rates. */
rb->pcm_set_frequency(NATIVE_FREQUENCY);
#if INPUT_SRC_CAPS != 0 #if INPUT_SRC_CAPS != 0
/* Select playback */ /* Select playback */
rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); rb->audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
@ -379,5 +385,4 @@ bool pcm_output_init(void)
void pcm_output_exit(void) void pcm_output_exit(void)
{ {
rb->pcm_set_frequency(HW_SAMPR_DEFAULT);
} }