Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

show track progress, current playtime & duration in web-ui #267

Merged
merged 2 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
77 changes: 74 additions & 3 deletions html/management.html
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@
width: 100%;
}

.progress-sm {
height: 0.4rem!important;
}

#SubTabContent.tab-content {
display: flex;
}
Expand Down Expand Up @@ -365,6 +369,11 @@ <h5 class="modal-title" data-i18n="tools.nvserase.title"></h5>
<div class="form-group col-md-12">
<legend data-i18n="control.current"></legend>
<div id="track"></div>
<div></div>
<div id="trackProgressDiv" class="progress progress-sm">
<div id="trackProgress" class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
</div>
<div id="playtime"> </div>
</div>
<br/>
<div class="form-group col-md-12">
Expand Down Expand Up @@ -775,21 +784,31 @@ <h5 class="modal-title" data-i18n="tools.nvserase.title"></h5>
<script type="text/javascript">
var DEBUG = false;
var lastIdclicked = '';
var ActiveTab = 'nav-rfid-tab';
var ActiveSubTab = 'rfid-music-tab';
var host = $(location).attr('hostname');
var language = navigator.language || navigator.userLanguage;
var localize;

/* show active / selected tab */
$('#nav-tab.nav-tabs a').on('shown.bs.tab', function (e) {
ActiveTab = $(e.target).attr('id');
console.log ("ActiveTab: " + ActiveTab);
if (ActiveTab == 'nav-control-tab') {
getTrackProgress();
}
});

/* show active / selected subtab */
$('#SubTab.nav-tabs a').on('shown.bs.tab', function (e) {
ActiveSubTab = $(e.target).attr('id');
console.log ( ActiveSubTab);
console.log ("ActiveSubTab: " + ActiveSubTab);
if (ActiveSubTab == 'rfid-music-tab') {
document.getElementById("fileOrUrl").required = true;
} else {
document.getElementById("fileOrUrl").required = false;
}
});
});

if (DEBUG) {
host = "192.168.178.114";
Expand Down Expand Up @@ -853,6 +872,21 @@ <h5 class="modal-title" data-i18n="tools.nvserase.title"></h5>
}
});

document.getElementById('trackProgressDiv').addEventListener('click', function (e) {
var bounds = this.getBoundingClientRect();
var max = bounds.width;
var pos = e.pageX - bounds.left;
var percent = Math.round(pos / max * 100);
console.log('track progress percentage:', percent);
var myObj = {
"trackProgress": {
posPercent: percent
}
};
var myJSON = JSON.stringify(myObj);
socket.send(myJSON);
});

function postRendering(event, data) {
Object.keys(data.instance._model.data).forEach(function (key, index) {

Expand Down Expand Up @@ -1459,6 +1493,7 @@ <h5 class="modal-title" data-i18n="tools.nvserase.title"></h5>

socket.onopen = function () {
setInterval(ping, 15000);
setInterval(getTrackProgress, 1000);
// clear old socket messages
socket.sendBuffer = [];
socket.send('{"settings":{"settings":"settings"}}'); // request settings
Expand Down Expand Up @@ -1501,7 +1536,7 @@ <h5 class="modal-title" data-i18n="tools.nvserase.title"></h5>
volumeSlider.setValue(parseInt(socketMsg.volume));
} if ("trackinfo" in socketMsg) {
document.getElementById('track').innerHTML = socketMsg.trackinfo.name;

setTrackProgress(socketMsg.trackinfo);
var btnTrackPlayPause = document.getElementById('nav-btn-play');
if (socketMsg.trackinfo.pausePlay) {
btnTrackPlayPause.innerHTML = '<i id="ico-play-pause" class="fas fa-lg fa-play"></i>';
Expand All @@ -1527,6 +1562,8 @@ <h5 class="modal-title" data-i18n="tools.nvserase.title"></h5>
btnTrackLast.classList.remove("disabled");
btnTrackNext.classList.remove("disabled");
}
} if ("trackProgress" in socketMsg) {
setTrackProgress(socketMsg.trackProgress);
} if ("coverimg" in socketMsg) {
document.getElementById('coverimg').src = "/cover?" + new Date().getTime();
} if ("settings" in socketMsg) {
Expand Down Expand Up @@ -1820,6 +1857,32 @@ <h5 class="modal-title" data-i18n="tools.nvserase.title"></h5>
clearTimeout(tm);
}

function getTrackProgress() {
if (ActiveTab !== 'nav-control-tab') {
return;
};

var myObj = {
"trackProgress": {
trackProgress: 'trackProgress'
}
};
var myJSON = JSON.stringify(myObj);
socket.send(myJSON);
}

function setTrackProgress(msg) {
// console.log(msg);
$("#trackProgress").css('width', msg.posPercent + "%");
if (msg.duration > 0) {
document.getElementById('playtime').innerHTML = secondsToTime(msg.time) + " / " + secondsToTime(msg.duration);
} else {
document.getElementById('playtime').innerHTML = "-- / --";
}
}



function genSettings(clickedId) {
lastIdclicked = clickedId;
var myObj = {
Expand Down Expand Up @@ -2016,6 +2079,14 @@ <h5 class="modal-title" data-i18n="tools.nvserase.title"></h5>
}
}

function secondsToTime(seconds) {
if (seconds < 3600) {
return new Date(seconds * 1000).toISOString().substring(14, 19);
} else {
return new Date(seconds * 1000).toISOString().slice(11, 19);
}
}

function secondsToDate(seconds) {
if (seconds == 0) {
return "--";
Expand Down
26 changes: 25 additions & 1 deletion src/AudioPlayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ static uint8_t AudioPlayer_MaxVolumeSpeaker = AUDIOPLAYER_VOLUME_MAX;
static uint8_t AudioPlayer_MinVolume = AUDIOPLAYER_VOLUME_MIN;
static uint8_t AudioPlayer_InitVolume = AUDIOPLAYER_VOLUME_INIT;

// current playtime
uint32_t AudioPlayer_CurrentTime;
uint32_t AudioPlayer_FileDuration;

// Playtime stats
time_t playTimeSecTotal = 0;
time_t playTimeSecSinceStart = 0;
Expand Down Expand Up @@ -217,6 +221,14 @@ time_t AudioPlayer_GetPlayTimeSinceStart(void) {
return (playTimeSecSinceStart * 1000);
}

uint32_t AudioPlayer_GetCurrentTime(void) {
return AudioPlayer_CurrentTime;
}

uint32_t AudioPlayer_GetFileDuration(void) {
return AudioPlayer_FileDuration;
}

void Audio_setTitle(const char *format, ...) {
char buf[256];
va_list args;
Expand Down Expand Up @@ -350,6 +362,8 @@ void AudioPlayer_Task(void *parameter) {
static BaseType_t trackQStatus;
static uint8_t trackCommand = NO_ACTION;
bool audioReturnCode;
AudioPlayer_CurrentTime = 0;
AudioPlayer_FileDuration = 0;

for (;;) {
/*
Expand All @@ -370,6 +384,9 @@ void AudioPlayer_Task(void *parameter) {
Log_Printf(LOGLEVEL_INFO, newCntrlReceivedQueue, trackCommand);
}

// update current playtime and duration
AudioPlayer_CurrentTime = audio->getAudioCurrentTime();
AudioPlayer_FileDuration = audio->getAudioFileDuration();
trackQStatus = xQueueReceive(gTrackQueue, &gPlayProperties.playlist, 0);
if (trackQStatus == pdPASS || gPlayProperties.trackFinished || trackCommand != NO_ACTION) {
if (trackQStatus == pdPASS) {
Expand Down Expand Up @@ -714,6 +731,13 @@ void AudioPlayer_Task(void *parameter) {
} else {
System_IndicateError();
}
} else if ((gPlayProperties.seekmode == SEEK_POS_PERCENT) && (gPlayProperties.currentRelPos > 0) && (gPlayProperties.currentRelPos < 100)) {
uint32_t newFilePos = uint32_t((double) (gPlayProperties.currentRelPos / 100) * audio->getFileSize());
if (audio->setFilePos(newFilePos)) {
Log_Printf(LOGLEVEL_NOTICE, JumpToPosition, newFilePos, audio->getFileSize());
} else {
System_IndicateError();
}
}
gPlayProperties.seekmode = SEEK_NORMAL;
}
Expand Down Expand Up @@ -782,7 +806,7 @@ void AudioPlayer_Task(void *parameter) {
// Calculate relative position in file (for neopixel) for SD-card-mode
if (!gPlayProperties.playlistFinished && !gPlayProperties.isWebstream) {
if (millis() % 20 == 0) { // Keep it simple
if (!gPlayProperties.pausePlay && (audio->getFileSize() > 0)) { // To progress necessary when paused
if (!gPlayProperties.pausePlay && (audio->getFileSize() > 0) && (gPlayProperties.seekmode != SEEK_POS_PERCENT)) { // To progress necessary when paused
gPlayProperties.currentRelPos = ((double) (audio->getFilePos() - audio->inBufferFilled()) / (double) audio->getFileSize()) * 100;
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/AudioPlayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,5 @@ bool Audio_Detect_Mode_HP(bool _state);
void Audio_setTitle(const char *format, ...);
time_t AudioPlayer_GetPlayTimeSinceStart(void);
time_t AudioPlayer_GetPlayTimeAllTime(void);
uint32_t AudioPlayer_GetCurrentTime(void);
uint32_t AudioPlayer_GetFileDuration(void);
1 change: 1 addition & 0 deletions src/LogMessages_DE.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ const char wrongWakeUpGpio[] = "Der gewählte GPIO ist nicht vom Typ RTC und unt
const char currentlyPlaying[] = "'%s' wird abgespielt (%d von %d)";
const char secondsJumpForward[] = "%d Sekunden nach vorne gesprungen";
const char secondsJumpBackward[] = "%d Sekunden zurück gesprungen";
const char JumpToPosition[] = "Sprung zu Position %u/%u";
const char wroteLastTrackToNvs[] = "Schreibe '%s' in NVS für RFID-Card-ID %s mit Abspielmodus %d und letzter Track %u";
const char wifiConnectionInProgress[] = "Versuche mit WLAN '%s' zu verbinden...";
const char wifiConnectionSuccess[] = "Verbunden mit WLAN '%s' (Signalstärke: %d dBm, Kanal: %d, MAC-Adresse: %s)";
Expand Down
1 change: 1 addition & 0 deletions src/LogMessages_EN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ const char wrongWakeUpGpio[] = "GPIO choosen as wakeup-pin isn't of type RTC and
const char currentlyPlaying[] = "'%s' is being played (%d of %d)";
const char secondsJumpForward[] = "Jumped %d seconds forwards";
const char secondsJumpBackward[] = "Jumped %d seconds backward";
const char JumpToPosition[] = "Jumped to position %u/%u";
const char wroteLastTrackToNvs[] = "Write '%s' to NVS for RFID-Card-ID %s with playmode %d and last track %u";
const char wifiConnectionInProgress[] = "Try to connect to WiFi with SSID '%s'...";
const char wifiConnectionSuccess[] = "Connected with WiFi '%s' (signal strength: %d dBm, channel: %d, BSSID: %s)";
Expand Down
20 changes: 19 additions & 1 deletion src/Web.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,12 @@ bool JSONToSettings(JsonObject doc) {
Web_SendWebsocketData(0, 60);
} else if (doc.containsKey("ssids")) {
Web_SendWebsocketData(0, 70);
} else if (doc.containsKey("trackProgress")) {
if (doc["trackProgress"].containsKey("posPercent")) {
gPlayProperties.seekmode = SEEK_POS_PERCENT;
gPlayProperties.currentRelPos = doc["trackProgress"]["posPercent"].as<uint8_t>();
}
Web_SendWebsocketData(0, 80);
}

return true;
Expand Down Expand Up @@ -953,6 +959,11 @@ bool processJsonRequest(char *_serialJson) {
// Sends JSON-answers via websocket
void Web_SendWebsocketData(uint32_t client, uint8_t code) {
if (!webserverStarted) {
// webserver not yet started
return;
}
if (ws.count() == 0) {
// we do not have any webclient connected
return;
}
char *jBuf = (char *) x_calloc(1024, sizeof(char));
Expand All @@ -977,6 +988,8 @@ void Web_SendWebsocketData(uint32_t client, uint8_t code) {
entry["numberOfTracks"] = gPlayProperties.numberOfTracks;
entry["volume"] = AudioPlayer_GetCurrentVolume();
entry["name"] = gPlayProperties.title;
entry["posPercent"] = gPlayProperties.currentRelPos;
entry["playMode"] = gPlayProperties.playMode;
} else if (code == 40) {
object["coverimg"] = "coverimg";
} else if (code == 50) {
Expand All @@ -987,6 +1000,11 @@ void Web_SendWebsocketData(uint32_t client, uint8_t code) {
} else if (code == 70) {
JsonObject entry = object.createNestedObject("settings");
settingsToJSON(entry, "ssids");
} else if (code == 80) {
JsonObject entry = object.createNestedObject("trackProgress");
entry["posPercent"] = gPlayProperties.currentRelPos;
entry["time"] = AudioPlayer_GetCurrentTime();
entry["duration"] = AudioPlayer_GetFileDuration();
};

serializeJson(doc, jBuf, 1024);
Expand Down Expand Up @@ -1024,7 +1042,7 @@ void onWebsocketEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsE
// Serial.printf("ws[%s][%u] %s-message[%llu]: ", server->url(), client->id(), (info->opcode == WS_TEXT) ? "text" : "binary", info->len);

if (processJsonRequest((char *) data)) {
if (data && (strncmp((char *) data, "getTrack", 8))) { // Don't send back ok-feedback if track's name is requested in background
if (data && (strncmp((char *) data, "track", 5))) { // Don't send back ok-feedback if track's name is requested in background
Web_SendWebsocketData(client->id(), 1);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/logmessages.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ extern const char wrongWakeUpGpio[];
extern const char currentlyPlaying[];
extern const char secondsJumpForward[];
extern const char secondsJumpBackward[];
extern const char JumpToPosition[];
extern const char wroteLastTrackToNvs[];
extern const char wifiConnectionInProgress[];
extern const char wifiConnectionSuccess[];
Expand Down
7 changes: 4 additions & 3 deletions src/values.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@
#define TRACK_N_PLAYLIST 3 // Repeat both (infinite loop)

// Seek-modes
#define SEEK_NORMAL 0 // Normal play
#define SEEK_FORWARDS 1 // Seek forwards
#define SEEK_BACKWARDS 2 // Seek backwards
#define SEEK_NORMAL 0 // Normal play
#define SEEK_FORWARDS 1 // Seek forwards
#define SEEK_BACKWARDS 2 // Seek backwards
#define SEEK_POS_PERCENT 3 // Seek to position (0-100)

// TTS
#define TTS_NONE 0 // Do nothng (IDLE)
Expand Down