Reworked the way the music player is keeping track of the play time of the current playing song so it doesn't desync when closing the player app or when the screen goes off
This commit is contained in:
parent
36285739ac
commit
50b12e4548
@ -559,7 +559,7 @@ void gfx_task(void *param)
|
||||
|
||||
music_player_screen_init(&musicPlayerScreen);
|
||||
music_player_screen_register_music_playback_control_cb(&musicPlayerScreen, &(sendMusicPlaybackBLECommandCb));
|
||||
music_player_screen_register_os_time_ms_ref_cb(&musicPlayerScreen, &(elapsed_ms));
|
||||
music_player_screen_register_music_player_time_ref_ms_cb(&musicPlayerScreen, &(elapsed_ms));
|
||||
|
||||
settings_screen_init(&settingsScreen);
|
||||
settings_screen_register_API_interface(&settingsScreen, &settingsScreenAPIInterface);
|
||||
|
@ -4,7 +4,10 @@
|
||||
#include "menu_screen.h"
|
||||
#include "translation.h"
|
||||
|
||||
void _set_UI_no_ble_connection(MusicPlayerScreen_t * const musicPlayerScreen, bool connected);
|
||||
static void _set_UI_no_ble_connection(MusicPlayerScreen_t * const musicPlayerScreen, bool connected);
|
||||
static void _update_playing_track_visuals(MusicPlayerScreen_t * const musicPlayerScreen);
|
||||
static void _update_playing_track_ref_time(MusicPlayerScreen_t * const musicPlayerScreen);
|
||||
static uint16_t _time_difference_in_ms(uint32_t referenceTimeMs, uint32_t currentTimeMs);
|
||||
|
||||
static void gesture_event_cb(lv_event_t *e)
|
||||
{
|
||||
@ -57,11 +60,37 @@ static void music_player_button_click_event_cb(lv_event_t *e)
|
||||
}
|
||||
else if(action == MUSIC_CONTROL_NEXT)
|
||||
{
|
||||
musicPlayerScreen->musicPlaybackCtrlCb(e->code == LV_EVENT_SHORT_CLICKED ? MUSIC_CONTROL_NEXT : MUSIC_CONTROL_FORWARD);
|
||||
if(e->code == LV_EVENT_SHORT_CLICKED)
|
||||
{
|
||||
musicPlayerScreen->musicPlaybackCtrlCb(MUSIC_CONTROL_NEXT);
|
||||
}
|
||||
else
|
||||
{
|
||||
musicPlayerScreen->musicPlaybackCtrlCb(MUSIC_CONTROL_FORWARD);
|
||||
//Don't forget to add 10 seconds to the current song position
|
||||
//10 seconds is the step used by the android AIMP player, this may vary
|
||||
musicPlayerScreen->currentMusicPosition = musicPlayerScreen->currentMusicPosition/1000 + FAST_FORWARD_BACKWARD_STEP > musicPlayerScreen->currentMusicDuration ?
|
||||
musicPlayerScreen->currentMusicDuration * 1000 : musicPlayerScreen->currentMusicPosition + FAST_FORWARD_BACKWARD_STEP * 1000;
|
||||
_update_playing_track_visuals(musicPlayerScreen);
|
||||
if(musicPlayerScreen->musicPlayerTimeRefmsCb)musicPlayerScreen->playerStartTimeRef = musicPlayerScreen->musicPlayerTimeRefmsCb();
|
||||
}
|
||||
}
|
||||
else if(action == MUSIC_CONTROL_PREVIOUS)
|
||||
{
|
||||
musicPlayerScreen->musicPlaybackCtrlCb(e->code == LV_EVENT_SHORT_CLICKED ? MUSIC_CONTROL_PREVIOUS : MUSIC_CONTROL_REWIND);
|
||||
if(e->code == LV_EVENT_SHORT_CLICKED)
|
||||
{
|
||||
musicPlayerScreen->musicPlaybackCtrlCb(MUSIC_CONTROL_PREVIOUS);
|
||||
}
|
||||
else
|
||||
{
|
||||
musicPlayerScreen->musicPlaybackCtrlCb(MUSIC_CONTROL_REWIND);
|
||||
//Don't forget to remove 10 seconds to the current song position
|
||||
//10 seconds is the step used by the android AIMP player, this may vary
|
||||
musicPlayerScreen->currentMusicPosition = musicPlayerScreen->currentMusicPosition >= FAST_FORWARD_BACKWARD_STEP * 1000 ?
|
||||
musicPlayerScreen->currentMusicPosition - FAST_FORWARD_BACKWARD_STEP * 1000 : 0;
|
||||
_update_playing_track_visuals(musicPlayerScreen);
|
||||
if(musicPlayerScreen->musicPlayerTimeRefmsCb)musicPlayerScreen->playerStartTimeRef = musicPlayerScreen->musicPlayerTimeRefmsCb();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -74,7 +103,11 @@ static void track_position_update_cb(lv_timer_t *timer)
|
||||
{
|
||||
MusicPlayerScreen_t *musicPlayerScreen = timer->user_data;
|
||||
|
||||
music_player_screen_set_music_position(musicPlayerScreen, ++musicPlayerScreen->currentMusicPosition);
|
||||
if(musicPlayerScreen->currentMusicPosition == musicPlayerScreen->currentMusicDuration * 1000) return;
|
||||
|
||||
//If the callback get's called, this means we are in the music play state
|
||||
_update_playing_track_ref_time(musicPlayerScreen);
|
||||
_update_playing_track_visuals(musicPlayerScreen);
|
||||
}
|
||||
|
||||
void music_player_screen_init(MusicPlayerScreen_t * const musicPlayerScreen)
|
||||
@ -100,7 +133,7 @@ void music_player_screen_register_music_playback_control_cb(MusicPlayerScreen_t
|
||||
musicPlayerScreen->musicPlaybackCtrlCb = musicPlaybackCtrlCb;
|
||||
}
|
||||
|
||||
void music_player_screen_register_os_time_ms_ref_cb(MusicPlayerScreen_t * const musicPlayerScreen, MusicPlayerTimeRefCb_t musicPlayerTimeRefCb)
|
||||
void music_player_screen_register_music_player_time_ref_ms_cb(MusicPlayerScreen_t * const musicPlayerScreen, MusicPlayerTimeRefmsCb_t musicPlayerTimeRefmsCb)
|
||||
{
|
||||
if(!musicPlayerScreen)
|
||||
{
|
||||
@ -108,7 +141,7 @@ void music_player_screen_register_os_time_ms_ref_cb(MusicPlayerScreen_t * const
|
||||
return;
|
||||
}
|
||||
|
||||
musicPlayerScreen->musicPlayerTimeRefCb = musicPlayerTimeRefCb;
|
||||
musicPlayerScreen->musicPlayerTimeRefmsCb = musicPlayerTimeRefmsCb;
|
||||
}
|
||||
|
||||
void music_player_screen_notify_BLE_connection_state(MusicPlayerScreen_t * const musicPlayerScreen, bool connected)
|
||||
@ -137,9 +170,7 @@ void music_player_screen_set_playing_music_title_and_artist(MusicPlayerScreen_t
|
||||
|
||||
if(title)
|
||||
{
|
||||
strncpy(musicPlayerScreen->titleText, title, sizeof musicPlayerScreen->titleText);
|
||||
musicPlayerScreen->titleText[sizeof(musicPlayerScreen->titleText) - 1] = '\0';
|
||||
|
||||
strncpy(musicPlayerScreen->titleText, title, sizeof(musicPlayerScreen->titleText)-1);
|
||||
if(musicPlayerScreen->titleLabel)
|
||||
{
|
||||
lv_label_set_text_static(musicPlayerScreen->titleLabel, musicPlayerScreen->titleText);
|
||||
@ -148,9 +179,7 @@ void music_player_screen_set_playing_music_title_and_artist(MusicPlayerScreen_t
|
||||
|
||||
if(artist)
|
||||
{
|
||||
strncpy(musicPlayerScreen->artistText, artist, sizeof musicPlayerScreen->artistText);
|
||||
musicPlayerScreen->artistText[sizeof(musicPlayerScreen->artistText) - 1] = '\0';
|
||||
|
||||
strncpy(musicPlayerScreen->artistText, artist, sizeof(musicPlayerScreen->artistText)-1);
|
||||
if(musicPlayerScreen->artistLabel)
|
||||
{
|
||||
lv_label_set_text_static(musicPlayerScreen->artistLabel, musicPlayerScreen->artistText);
|
||||
@ -188,22 +217,13 @@ void music_player_screen_set_music_position(MusicPlayerScreen_t * const musicPla
|
||||
}
|
||||
|
||||
positionInSeconds = positionInSeconds > musicPlayerScreen->currentMusicDuration ? musicPlayerScreen->currentMusicDuration : positionInSeconds;
|
||||
musicPlayerScreen->currentMusicPosition = positionInSeconds;
|
||||
musicPlayerScreen->currentMusicPosition = positionInSeconds * 1000;
|
||||
|
||||
//Let's update the time ref
|
||||
if(musicPlayerScreen->musicPlayerTimeRefCb)
|
||||
musicPlayerScreen->osTimeRef = musicPlayerScreen->musicPlayerTimeRefCb();
|
||||
|
||||
//If the widget is currently displayed, we update it as well !
|
||||
if(!musicPlayerScreen->playbackArc) return;
|
||||
|
||||
lv_arc_set_value(musicPlayerScreen->playbackArc, musicPlayerScreen->currentMusicPosition);
|
||||
|
||||
if(positionInSeconds < 3600)sprintf(musicPlayerScreen->positionTimeLabel.text, "%s%u:%s%u", positionInSeconds / 60 < 10 ? "0":"", positionInSeconds / 60, positionInSeconds % 60 < 10 ? "0":"", positionInSeconds % 60);
|
||||
else sprintf(musicPlayerScreen->positionTimeLabel.text, "%s%u:%s%u:%s%u", positionInSeconds / 3600 < 10 ? "0":"", positionInSeconds / 3600,
|
||||
(positionInSeconds % 3600) / 60 < 10 ? "0":"", (positionInSeconds % 3600) / 60,
|
||||
(positionInSeconds % 3600) % 60 < 10 ? "0":"", (positionInSeconds % 3600) % 60);
|
||||
lv_label_set_text_static(musicPlayerScreen->positionTimeLabel.label, musicPlayerScreen->positionTimeLabel.text);
|
||||
//Let's update the current music position visually
|
||||
if(music_player_screen_is_in_use(musicPlayerScreen))
|
||||
{
|
||||
_update_playing_track_visuals(musicPlayerScreen);
|
||||
}
|
||||
}
|
||||
|
||||
void music_player_screen_set_music_playing_state(MusicPlayerScreen_t * const musicPlayerScreen, MusicPlaybackCtrlAction_e playingState)
|
||||
@ -218,12 +238,15 @@ void music_player_screen_set_music_playing_state(MusicPlayerScreen_t * const mus
|
||||
|
||||
musicPlayerScreen->currentPlayState = playingState;
|
||||
|
||||
if(musicPlayerScreen->currentPlayState == MUSIC_CONTROL_PLAY)
|
||||
lv_timer_resume(musicPlayerScreen->timePositionTimer);
|
||||
else
|
||||
lv_timer_pause(musicPlayerScreen->timePositionTimer);
|
||||
if(musicPlayerScreen->musicPlayerTimeRefmsCb)
|
||||
musicPlayerScreen->playerStartTimeRef = musicPlayerScreen->musicPlayerTimeRefmsCb();
|
||||
|
||||
if(!musicPlayerScreen->playPauseBtn.label) return;
|
||||
if(!music_player_screen_is_in_use(musicPlayerScreen)) return;
|
||||
|
||||
if(musicPlayerScreen->currentPlayState == MUSIC_CONTROL_PLAY)
|
||||
lv_timer_resume(musicPlayerScreen->trackPlayCursorUpdateTimer);
|
||||
else
|
||||
lv_timer_pause(musicPlayerScreen->trackPlayCursorUpdateTimer);
|
||||
|
||||
strcpy(musicPlayerScreen->playPauseBtn.icon, musicPlayerScreen->currentPlayState == MUSIC_CONTROL_PLAY ? LV_SYMBOL_PAUSE : LV_SYMBOL_PLAY);
|
||||
lv_label_set_text_static(musicPlayerScreen->playPauseBtn.label, musicPlayerScreen->playPauseBtn.icon);
|
||||
@ -419,23 +442,17 @@ void music_player_screen_create(MusicPlayerScreen_t * const musicPlayerScreen)
|
||||
|
||||
_set_UI_no_ble_connection(musicPlayerScreen, musicPlayerScreen->ble_connection_state);
|
||||
|
||||
if(musicPlayerScreen->timePositionTimer)
|
||||
if(musicPlayerScreen->trackPlayCursorUpdateTimer)
|
||||
{
|
||||
LV_LOG_ERROR("timePositionTimer should be NULL here !");
|
||||
lv_timer_del(musicPlayerScreen->timePositionTimer);
|
||||
musicPlayerScreen->timePositionTimer = NULL;
|
||||
LV_LOG_ERROR("trackPlayCursorUpdateTimer should be NULL here !");
|
||||
lv_timer_del(musicPlayerScreen->trackPlayCursorUpdateTimer);
|
||||
musicPlayerScreen->trackPlayCursorUpdateTimer = NULL;
|
||||
}
|
||||
musicPlayerScreen->timePositionTimer = lv_timer_create(&(track_position_update_cb), 1000, musicPlayerScreen);
|
||||
//If the music was not currently playing, no need to start the music position update timer
|
||||
if(musicPlayerScreen->currentPlayState != MUSIC_CONTROL_PLAY)
|
||||
{
|
||||
lv_timer_pause(musicPlayerScreen->timePositionTimer);
|
||||
}
|
||||
else if(musicPlayerScreen->musicPlayerTimeRefCb) //When we left the app, the music was running so we need to recompute the current position
|
||||
{
|
||||
musicPlayerScreen->currentMusicPosition += (musicPlayerScreen->musicPlayerTimeRefCb() - musicPlayerScreen->osTimeRef) / 1000; //We want seconds
|
||||
}
|
||||
music_player_screen_set_music_position(musicPlayerScreen, musicPlayerScreen->currentMusicPosition);
|
||||
musicPlayerScreen->trackPlayCursorUpdateTimer = lv_timer_create(&(track_position_update_cb), 333, musicPlayerScreen);
|
||||
if(musicPlayerScreen->currentPlayState != MUSIC_CONTROL_PLAY) lv_timer_pause(musicPlayerScreen->trackPlayCursorUpdateTimer);
|
||||
if(musicPlayerScreen->currentPlayState == MUSIC_CONTROL_PLAY) _update_playing_track_ref_time(musicPlayerScreen);
|
||||
|
||||
_update_playing_track_visuals(musicPlayerScreen);
|
||||
|
||||
//We register the event callback to handle gestures
|
||||
lv_obj_add_event_cb(musicPlayerScreen->display, &(gesture_event_cb), LV_EVENT_GESTURE, musicPlayerScreen);
|
||||
@ -450,12 +467,11 @@ void music_player_screen_destroy(MusicPlayerScreen_t * const musicPlayerScreen)
|
||||
LV_LOG_ERROR("NULL pointer given !");
|
||||
return;
|
||||
}
|
||||
|
||||
lv_timer_del(musicPlayerScreen->timePositionTimer);
|
||||
lv_timer_del(musicPlayerScreen->trackPlayCursorUpdateTimer);
|
||||
memset(musicPlayerScreen, 0, offsetof(MusicPlayerScreen_t, musicPlaybackCtrlCb));
|
||||
}
|
||||
|
||||
void _set_UI_no_ble_connection(MusicPlayerScreen_t * const musicPlayerScreen, bool connected)
|
||||
static void _set_UI_no_ble_connection(MusicPlayerScreen_t * const musicPlayerScreen, bool connected)
|
||||
{
|
||||
if(connected)
|
||||
{
|
||||
@ -479,3 +495,32 @@ void _set_UI_no_ble_connection(MusicPlayerScreen_t * const musicPlayerScreen, bo
|
||||
lv_obj_add_flag(musicPlayerScreen->artistLabel, LV_OBJ_FLAG_HIDDEN);
|
||||
}
|
||||
}
|
||||
|
||||
static void _update_playing_track_visuals(MusicPlayerScreen_t * const musicPlayerScreen)
|
||||
{
|
||||
//Do not forget to put the current music position back in seconds
|
||||
uint16_t positionInSeconds = musicPlayerScreen->currentMusicPosition/1000;
|
||||
lv_arc_set_value(musicPlayerScreen->playbackArc, positionInSeconds);
|
||||
|
||||
if(positionInSeconds < 3600)sprintf(musicPlayerScreen->positionTimeLabel.text, "%s%u:%s%u", positionInSeconds / 60 < 10 ? "0":"", positionInSeconds / 60, positionInSeconds % 60 < 10 ? "0":"", positionInSeconds % 60);
|
||||
else sprintf(musicPlayerScreen->positionTimeLabel.text, "%s%u:%s%u:%s%u", positionInSeconds / 3600 < 10 ? "0":"", positionInSeconds / 3600,
|
||||
(positionInSeconds % 3600) / 60 < 10 ? "0":"", (positionInSeconds % 3600) / 60,
|
||||
(positionInSeconds % 3600) % 60 < 10 ? "0":"", (positionInSeconds % 3600) % 60);
|
||||
lv_label_set_text_static(musicPlayerScreen->positionTimeLabel.label, musicPlayerScreen->positionTimeLabel.text);
|
||||
}
|
||||
|
||||
static void _update_playing_track_ref_time(MusicPlayerScreen_t * const musicPlayerScreen)
|
||||
{
|
||||
//Let's compute the time that has passed and update the current song position
|
||||
uint32_t currentTimeMs = musicPlayerScreen->musicPlayerTimeRefmsCb ? musicPlayerScreen->musicPlayerTimeRefmsCb() : 0;
|
||||
uint16_t timeDifferenceMs = _time_difference_in_ms(musicPlayerScreen->playerStartTimeRef, currentTimeMs);
|
||||
musicPlayerScreen->playerStartTimeRef = currentTimeMs;
|
||||
|
||||
musicPlayerScreen->currentMusicPosition = musicPlayerScreen->currentMusicPosition + timeDifferenceMs > musicPlayerScreen->currentMusicDuration * 1000 ?
|
||||
musicPlayerScreen->currentMusicDuration * 1000 : musicPlayerScreen->currentMusicPosition + timeDifferenceMs;
|
||||
}
|
||||
|
||||
static uint16_t _time_difference_in_ms(uint32_t referenceTimeMs, uint32_t currentTimeMs)
|
||||
{
|
||||
return currentTimeMs - referenceTimeMs;
|
||||
}
|
||||
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include "lvgl.h"
|
||||
|
||||
#define FAST_FORWARD_BACKWARD_STEP (10)
|
||||
|
||||
typedef enum MusicPlaybackCtrlAction
|
||||
{
|
||||
MUSIC_CONTROL_PLAY = 0,
|
||||
@ -17,7 +19,7 @@ typedef enum MusicPlaybackCtrlAction
|
||||
} MusicPlaybackCtrlAction_e;
|
||||
|
||||
typedef void (*MusicPlaybackCtrlCb_t)(MusicPlaybackCtrlAction_e musicPlaybackCtrlAction);
|
||||
typedef uint32_t (*MusicPlayerTimeRefCb_t)(void);
|
||||
typedef uint32_t (*MusicPlayerTimeRefmsCb_t)(void);
|
||||
|
||||
typedef struct PlayerButton
|
||||
{
|
||||
@ -45,16 +47,16 @@ typedef struct MusicPlayerScreen
|
||||
lv_obj_t *titleLabel;
|
||||
lv_obj_t *artistLabel;
|
||||
TimeLabel_t positionTimeLabel, durationTimeLabel;
|
||||
lv_timer_t *timePositionTimer;
|
||||
lv_timer_t *trackPlayCursorUpdateTimer;
|
||||
//Should not be erased attributes
|
||||
MusicPlaybackCtrlCb_t musicPlaybackCtrlCb;
|
||||
MusicPlayerTimeRefCb_t musicPlayerTimeRefCb;
|
||||
MusicPlayerTimeRefmsCb_t musicPlayerTimeRefmsCb;
|
||||
MusicPlaybackCtrlAction_e currentPlayState;
|
||||
uint16_t currentMusicDuration; //The currently playing music's total duration in seconds.
|
||||
uint16_t currentMusicPosition; //The currently playing music's cursor position in seconds.
|
||||
uint32_t osTimeRef; //Time reference used to compute the time elaspsed when the player is not running, but the song is playing.
|
||||
char titleText[60];
|
||||
char artistText[30];
|
||||
uint16_t currentMusicDuration; //The currently playing music's total duration in seconds.
|
||||
uint32_t currentMusicPosition; //The currently playing music's cursor position in milliseconds.
|
||||
uint32_t playerStartTimeRef;
|
||||
bool ble_connection_state;
|
||||
} MusicPlayerScreen_t;
|
||||
|
||||
@ -68,7 +70,7 @@ void music_player_screen_init(MusicPlayerScreen_t * const musicPlayerScreen);
|
||||
|
||||
void music_player_screen_register_music_playback_control_cb(MusicPlayerScreen_t * const musicPlayerScreen, MusicPlaybackCtrlCb_t musicPlaybackCtrlCb);
|
||||
|
||||
void music_player_screen_register_os_time_ms_ref_cb(MusicPlayerScreen_t * const musicPlayerScreen, MusicPlayerTimeRefCb_t musicPlayerTimeRefCb);
|
||||
void music_player_screen_register_music_player_time_ref_ms_cb(MusicPlayerScreen_t * const musicPlayerScreen, MusicPlayerTimeRefmsCb_t musicPlayerTimeRefmsCb);
|
||||
|
||||
void music_player_screen_notify_BLE_connection_state(MusicPlayerScreen_t * const musicPlayerScreen, bool connected);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user