Rewriting the music player to have a better sync between phone track play time and what is displayed on the watch

This commit is contained in:
anschrammh 2023-09-21 12:47:20 +02:00
parent f5d3e33dab
commit b0ba6c36e4
2 changed files with 87 additions and 30 deletions

View File

@ -3,7 +3,9 @@
#include "music_player_screen.h" #include "music_player_screen.h"
#include "menu_screen.h" #include "menu_screen.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_position(MusicPlayerScreen_t * const musicPlayerScreen, uint16_t positionInSeconds);
static uint16_t _time_difference_in_seconds(uint32_t referenceTimeMs, uint32_t currentTimeMs);
static void gesture_event_cb(lv_event_t *e) static void gesture_event_cb(lv_event_t *e)
{ {
@ -56,11 +58,30 @@ static void music_player_button_click_event_cb(lv_event_t *e)
} }
else if(action == MUSIC_CONTROL_NEXT) else if(action == MUSIC_CONTROL_NEXT)
{ {
musicPlayerScreen->musicPlaybackCtrlCb(e->code == LV_EVENT_SHORT_CLICKED ? MUSIC_CONTROL_FORWARD : MUSIC_CONTROL_NEXT); 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
music_player_screen_set_music_position(musicPlayerScreen, musicPlayerScreen->currentMusicPosition + 10);
}
} }
else if(action == MUSIC_CONTROL_PREVIOUS) else if(action == MUSIC_CONTROL_PREVIOUS)
{ {
musicPlayerScreen->musicPlaybackCtrlCb(e->code == LV_EVENT_SHORT_CLICKED ? MUSIC_CONTROL_REWIND : MUSIC_CONTROL_PREVIOUS); 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
uint16_t musicPositionToSet = musicPlayerScreen->currentMusicPosition >= 10 ? musicPlayerScreen->currentMusicPosition - 10 : 0;
music_player_screen_set_music_position(musicPlayerScreen, musicPositionToSet);
}
} }
else else
{ {
@ -72,8 +93,12 @@ static void music_player_button_click_event_cb(lv_event_t *e)
static void track_position_update_cb(lv_timer_t *timer) static void track_position_update_cb(lv_timer_t *timer)
{ {
MusicPlayerScreen_t *musicPlayerScreen = timer->user_data; MusicPlayerScreen_t *musicPlayerScreen = timer->user_data;
uint32_t current_time = musicPlayerScreen->musicPlayerTimeRefmsCb ? musicPlayerScreen->musicPlayerTimeRefmsCb() : 0;
music_player_screen_set_music_position(musicPlayerScreen, ++musicPlayerScreen->currentMusicPosition); _update_playing_track_position(
musicPlayerScreen,
musicPlayerScreen->currentMusicPosition +
_time_difference_in_seconds(musicPlayerScreen->playerStartTimeRef, current_time)
);
} }
void music_player_screen_init(MusicPlayerScreen_t * const musicPlayerScreen) void music_player_screen_init(MusicPlayerScreen_t * const musicPlayerScreen)
@ -99,6 +124,17 @@ void music_player_screen_register_music_playback_control_cb(MusicPlayerScreen_t
musicPlayerScreen->musicPlaybackCtrlCb = musicPlaybackCtrlCb; musicPlayerScreen->musicPlaybackCtrlCb = musicPlaybackCtrlCb;
} }
void music_player_screen_register_music_player_time_ref_ms_cb(MusicPlayerScreen_t * const musicPlayerScreen, MusicPlayerTimeRefmsCb_t musicPlayerTimeRefmsCb)
{
if(!musicPlayerScreen)
{
LV_LOG_ERROR("NULL pointer given !");
return;
}
musicPlayerScreen->musicPlayerTimeRefmsCb = musicPlayerTimeRefmsCb;
}
void music_player_screen_notify_BLE_connection_state(MusicPlayerScreen_t * const musicPlayerScreen, bool connected) void music_player_screen_notify_BLE_connection_state(MusicPlayerScreen_t * const musicPlayerScreen, bool connected)
{ {
if(!musicPlayerScreen) if(!musicPlayerScreen)
@ -178,16 +214,7 @@ void music_player_screen_set_music_position(MusicPlayerScreen_t * const musicPla
positionInSeconds = positionInSeconds > musicPlayerScreen->currentMusicDuration ? musicPlayerScreen->currentMusicDuration : positionInSeconds; positionInSeconds = positionInSeconds > musicPlayerScreen->currentMusicDuration ? musicPlayerScreen->currentMusicDuration : positionInSeconds;
musicPlayerScreen->currentMusicPosition = positionInSeconds; musicPlayerScreen->currentMusicPosition = positionInSeconds;
//If the widget is currently displayed, we update it as well ! _update_playing_track_position(musicPlayerScreen, positionInSeconds);
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);
} }
void music_player_screen_set_music_playing_state(MusicPlayerScreen_t * const musicPlayerScreen, MusicPlaybackCtrlAction_e playingState) void music_player_screen_set_music_playing_state(MusicPlayerScreen_t * const musicPlayerScreen, MusicPlaybackCtrlAction_e playingState)
@ -202,12 +229,15 @@ void music_player_screen_set_music_playing_state(MusicPlayerScreen_t * const mus
musicPlayerScreen->currentPlayState = playingState; musicPlayerScreen->currentPlayState = playingState;
if(musicPlayerScreen->currentPlayState == MUSIC_CONTROL_PLAY) if(musicPlayerScreen->musicPlayerTimeRefmsCb)
lv_timer_resume(musicPlayerScreen->timePositionTimer); musicPlayerScreen->playerStartTimeRef = musicPlayerScreen->musicPlayerTimeRefmsCb();
else
lv_timer_pause(musicPlayerScreen->timePositionTimer);
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); 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); lv_label_set_text_static(musicPlayerScreen->playPauseBtn.label, musicPlayerScreen->playPauseBtn.icon);
@ -400,18 +430,18 @@ void music_player_screen_create(MusicPlayerScreen_t * const musicPlayerScreen)
lv_obj_set_style_arc_color(musicPlayerScreen->playbackArc, lv_palette_main(LV_PALETTE_LIME), LV_PART_INDICATOR); lv_obj_set_style_arc_color(musicPlayerScreen->playbackArc, lv_palette_main(LV_PALETTE_LIME), LV_PART_INDICATOR);
lv_obj_set_style_arc_color(musicPlayerScreen->playbackArc, lv_color_make(100,100,100), LV_PART_MAIN); lv_obj_set_style_arc_color(musicPlayerScreen->playbackArc, lv_color_make(100,100,100), LV_PART_MAIN);
music_player_screen_set_music_duration(musicPlayerScreen, musicPlayerScreen->currentMusicDuration); music_player_screen_set_music_duration(musicPlayerScreen, musicPlayerScreen->currentMusicDuration);
music_player_screen_set_music_position(musicPlayerScreen, musicPlayerScreen->currentMusicPosition); _update_playing_track_position(musicPlayerScreen, musicPlayerScreen->currentMusicPosition);
_set_UI_no_ble_connection(musicPlayerScreen, musicPlayerScreen->ble_connection_state); _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_LOG_ERROR("trackPlayCursorUpdateTimer should be NULL here !");
lv_timer_del(musicPlayerScreen->timePositionTimer); lv_timer_del(musicPlayerScreen->trackPlayCursorUpdateTimer);
musicPlayerScreen->timePositionTimer = NULL; musicPlayerScreen->trackPlayCursorUpdateTimer = NULL;
} }
musicPlayerScreen->timePositionTimer = lv_timer_create(&(track_position_update_cb), 1000, musicPlayerScreen); musicPlayerScreen->trackPlayCursorUpdateTimer = lv_timer_create(&(track_position_update_cb), 1000, musicPlayerScreen);
if(musicPlayerScreen->currentPlayState != MUSIC_CONTROL_PLAY) lv_timer_pause(musicPlayerScreen->timePositionTimer); if(musicPlayerScreen->currentPlayState != MUSIC_CONTROL_PLAY) lv_timer_pause(musicPlayerScreen->trackPlayCursorUpdateTimer);
//We register the event callback to handle gestures //We register the event callback to handle gestures
lv_obj_add_event_cb(musicPlayerScreen->display, &(gesture_event_cb), LV_EVENT_GESTURE, musicPlayerScreen); lv_obj_add_event_cb(musicPlayerScreen->display, &(gesture_event_cb), LV_EVENT_GESTURE, musicPlayerScreen);
@ -426,11 +456,11 @@ void music_player_screen_destroy(MusicPlayerScreen_t * const musicPlayerScreen)
LV_LOG_ERROR("NULL pointer given !"); LV_LOG_ERROR("NULL pointer given !");
return; return;
} }
lv_timer_del(musicPlayerScreen->timePositionTimer); lv_timer_del(musicPlayerScreen->trackPlayCursorUpdateTimer);
memset(musicPlayerScreen, 0, offsetof(MusicPlayerScreen_t, musicPlaybackCtrlCb)); 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) if(connected)
{ {
@ -454,3 +484,25 @@ void _set_UI_no_ble_connection(MusicPlayerScreen_t * const musicPlayerScreen, bo
lv_obj_add_flag(musicPlayerScreen->artistLabel, LV_OBJ_FLAG_HIDDEN); lv_obj_add_flag(musicPlayerScreen->artistLabel, LV_OBJ_FLAG_HIDDEN);
} }
} }
static void _update_playing_track_position(MusicPlayerScreen_t * const musicPlayerScreen, uint16_t positionInSeconds)
{
//If the widget is currently displayed, we update it as well !
if(!musicPlayerScreen->playbackArc) return;
//Let's check that the track current position is not greater than the track's duration
positionInSeconds = positionInSeconds > musicPlayerScreen->currentMusicDuration ? musicPlayerScreen->currentMusicDuration : positionInSeconds;
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 uint16_t _time_difference_in_seconds(uint32_t referenceTimeMs, uint32_t currentTimeMs)
{
return (currentTimeMs - referenceTimeMs)/1000;
}

View File

@ -17,6 +17,7 @@ typedef enum MusicPlaybackCtrlAction
} MusicPlaybackCtrlAction_e; } MusicPlaybackCtrlAction_e;
typedef void (*MusicPlaybackCtrlCb_t)(MusicPlaybackCtrlAction_e musicPlaybackCtrlAction); typedef void (*MusicPlaybackCtrlCb_t)(MusicPlaybackCtrlAction_e musicPlaybackCtrlAction);
typedef uint32_t (*MusicPlayerTimeRefmsCb_t)(void);
typedef struct PlayerButton typedef struct PlayerButton
{ {
@ -44,14 +45,16 @@ typedef struct MusicPlayerScreen
lv_obj_t *titleLabel; lv_obj_t *titleLabel;
lv_obj_t *artistLabel; lv_obj_t *artistLabel;
TimeLabel_t positionTimeLabel, durationTimeLabel; TimeLabel_t positionTimeLabel, durationTimeLabel;
lv_timer_t *timePositionTimer; lv_timer_t *trackPlayCursorUpdateTimer;
//Should not be erased attributes //Should not be erased attributes
MusicPlaybackCtrlCb_t musicPlaybackCtrlCb; MusicPlaybackCtrlCb_t musicPlaybackCtrlCb;
MusicPlayerTimeRefmsCb_t musicPlayerTimeRefmsCb;
MusicPlaybackCtrlAction_e currentPlayState; MusicPlaybackCtrlAction_e currentPlayState;
char titleText[60]; char titleText[60];
char artistText[30]; char artistText[30];
uint16_t currentMusicDuration; //The currently playing music's total duration in seconds. uint16_t currentMusicDuration; //The currently playing music's total duration in seconds.
uint16_t currentMusicPosition; //The currently playing music's cursor position in seconds. uint16_t currentMusicPosition; //The currently playing music's cursor position in seconds.
uint32_t playerStartTimeRef;
bool ble_connection_state; bool ble_connection_state;
} MusicPlayerScreen_t; } MusicPlayerScreen_t;
@ -59,6 +62,8 @@ 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_music_playback_control_cb(MusicPlayerScreen_t * const musicPlayerScreen, MusicPlaybackCtrlCb_t musicPlaybackCtrlCb);
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); void music_player_screen_notify_BLE_connection_state(MusicPlayerScreen_t * const musicPlayerScreen, bool connected);
void music_player_screen_set_playing_music_title_and_artist(MusicPlayerScreen_t * const musicPlayerScreen, const char *title, const char *artist); void music_player_screen_set_playing_music_title_and_artist(MusicPlayerScreen_t * const musicPlayerScreen, const char *title, const char *artist);