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

bugfixes/better handling of coverimage #127

Merged
merged 1 commit into from Dec 2, 2021
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
11 changes: 9 additions & 2 deletions html/management_DE.html
Expand Up @@ -824,7 +824,7 @@

if(data.dir) {
type = "folder";
} else if ((/\.(mp3|MP3|ogg|wav|WAV|OGG|wma|WMA|acc|ACC|flac|FLAC)$/i).test(data.name)) {
} else if ((/\.(mp3|MP3|ogg|wav|WAV|OGG|wma|WMA|acc|ACC|m4a|M4A|flac|FLAC)$/i).test(data.name)) {
type = "audio";
} else {
type = "file";
Expand Down Expand Up @@ -904,7 +904,14 @@
items.play = {
label: "Abspielen",
action: function(x) {
var playMode = node.data.directory?"5":"1";
var playMode = 1;
if (node.data.directory) {
playMode = 5;
} else {
if ((/\.(m3u|M3U)$/i).test(node.data.path)) {
playMode = 11;
}
}
postData("/exploreraudio?path=" + node.data.path + "&playmode=" + playMode);
}
};
Expand Down
40 changes: 16 additions & 24 deletions src/AudioPlayer.cpp
Expand Up @@ -101,7 +101,7 @@ void AudioPlayer_Init(void) {
AudioPlayer_SetupVolume();

// delete cover image
gFSystem.remove("/.cover");
gPlayProperties.coverFileName = NULL;
if (System_GetOperationMode() == OPMODE_NORMAL) { // Don't start audio-task in BT-mode!
xTaskCreatePinnedToCore(
AudioPlayer_Task, /* Function to implement the task */
Expand Down Expand Up @@ -363,10 +363,10 @@ void AudioPlayer_Task(void *parameter) {
if (gPlayProperties.title) {
free(gPlayProperties.title);
gPlayProperties.title = NULL;
}
}
Web_SendWebsocketData(0, 30);
// delete cover image
gFSystem.remove("/.cover");
gPlayProperties.coverFileName = NULL;
Web_SendWebsocketData(0, 40);
continue;

Expand Down Expand Up @@ -458,9 +458,9 @@ void AudioPlayer_Task(void *parameter) {
if (gPlayProperties.title) {
free(gPlayProperties.title);
gPlayProperties.title = NULL;
}
}
// delete cover image
gFSystem.remove("/.cover");
gPlayProperties.coverFileName = NULL;
Web_SendWebsocketData(0, 40);
audioReturnCode = audio->connecttoFS(gFSystem, *(gPlayProperties.playlist + gPlayProperties.currentTrackNumber));
// consider track as finished, when audio lib call was not successful
Expand Down Expand Up @@ -598,9 +598,9 @@ void AudioPlayer_Task(void *parameter) {
if (gPlayProperties.title) {
free(gPlayProperties.title);
gPlayProperties.title = NULL;
}
}
// delete cover image
gFSystem.remove("/.cover");
gPlayProperties.coverFileName = NULL;
Web_SendWebsocketData(0, 40);
audioReturnCode = audio->connecttohost(*(gPlayProperties.playlist + gPlayProperties.currentTrackNumber));
gPlayProperties.playlistFinished = false;
Expand All @@ -617,9 +617,9 @@ void AudioPlayer_Task(void *parameter) {
if (gPlayProperties.title) {
free(gPlayProperties.title);
gPlayProperties.title = NULL;
}
}
// delete cover image
gFSystem.remove("/.cover");
gPlayProperties.coverFileName = NULL;
Web_SendWebsocketData(0, 40);
audioReturnCode = audio->connecttoFS(gFSystem, *(gPlayProperties.playlist + gPlayProperties.currentTrackNumber));
// consider track as finished, when audio lib call was not successful
Expand Down Expand Up @@ -1104,11 +1104,11 @@ void audio_id3data(const char *info) { //id3 metadata
// copy title
if (!gPlayProperties.title) {
gPlayProperties.title = (char *) x_malloc(sizeof(char) * 255);
}
}
strncpy(gPlayProperties.title, info + 6, 255);
// notify web ui
Web_SendWebsocketData(0, 30);
}
}
}

void audio_eof_mp3(const char *info) { //end of file
Expand Down Expand Up @@ -1170,19 +1170,11 @@ void audio_lasthost(const char *info) { //stream URL played
}

// id3 tag: save cover image
void audio_id3image(File& file, const size_t pos, const size_t size) {

// save raw image data to file "/.cover"
snprintf(Log_Buffer, Log_BufferLength, "save album cover image: \"%s\"", (char *) file.name());
Log_Println(Log_Buffer, LOGLEVEL_INFO);
file.seek(pos);
File coverFile = gFSystem.open("/.cover", FILE_WRITE);
uint8_t buf[255];
while(file.position() < (pos + size)) {
int bytesRead = file.read(buf, sizeof(buf));
coverFile.write( buf, bytesRead);
}
coverFile.close();
void audio_id3image(File& file, const size_t pos, const size_t size) {
// save cover image file and position/size for later use
gPlayProperties.coverFileName = (char *)(file.name());
gPlayProperties.coverFilePos = pos;
gPlayProperties.coverFileSize = size;
// websocket notify cover image has changed
Web_SendWebsocketData(0, 40);
}
Expand Down
3 changes: 3 additions & 0 deletions src/AudioPlayer.h
Expand Up @@ -25,6 +25,9 @@ typedef struct { // Bit field
bool tellIpAddress: 1; // If true current IP-address is spoken
bool currentSpeechActive: 1; // If speech-play is active
bool lastSpeechActive: 1; // If speech-play was active
char *coverFileName; // current coverfile
size_t coverFilePos; // current cover file position
size_t coverFileSize; // current cover file size
} playProps;

extern playProps gPlayProperties;
Expand Down
11 changes: 9 additions & 2 deletions src/HTMLmanagement_DE.h
Expand Up @@ -824,7 +824,7 @@ static const char management_HTML[] PROGMEM = "<!DOCTYPE html> \
\
if(data.dir) {\
type = \"folder\";\
} else if ((/\\.(mp3|MP3|ogg|wav|WAV|OGG|wma|WMA|acc|ACC|flac|FLAC)$/i).test(data.name)) {\
} else if ((/\\.(mp3|MP3|ogg|wav|WAV|OGG|wma|WMA|acc|ACC|m4a|M4A|flac|FLAC)$/i).test(data.name)) {\
type = \"audio\";\
} else {\
type = \"file\";\
Expand Down Expand Up @@ -904,7 +904,14 @@ static const char management_HTML[] PROGMEM = "<!DOCTYPE html> \
items.play = {\
label: \"Abspielen\",\
action: function(x) {\
var playMode = node.data.directory?\"5\":\"1\";\
var playMode = 1;\
if (node.data.directory) {\
playMode = 5; \
} else {\
if ((/\\.(m3u|M3U)$/i).test(node.data.path)) {\
playMode = 11;\
}\
} \
postData(\"/exploreraudio?path=\" + node.data.path + \"&playmode=\" + playMode);\
}\
};\
Expand Down
24 changes: 15 additions & 9 deletions src/Web.cpp
Expand Up @@ -577,8 +577,13 @@ void Web_SendWebsocketData(uint32_t client, uint8_t code) {
entry["volume"] = AudioPlayer_GetCurrentVolume();
if (gPlayProperties.title) {
// show current audio title from id3 metadata
if (gPlayProperties.numberOfTracks > 1) {
snprintf(Log_Buffer, Log_BufferLength, "(%u / %u): %s", gPlayProperties.currentTrackNumber+1, gPlayProperties.numberOfTracks, gPlayProperties.title);
} else {
snprintf(Log_Buffer, Log_BufferLength, "%s", gPlayProperties.title);
};
char utf8Buffer[200];
convertAsciiToUtf8(gPlayProperties.title, utf8Buffer);
convertAsciiToUtf8(Log_Buffer, utf8Buffer);
entry["name"] = utf8Buffer;
} else if (gPlayProperties.playMode == NO_PLAYLIST) {
// no active playlist
Expand Down Expand Up @@ -1135,10 +1140,10 @@ bool Web_DumpNvsToSd(const char *_namespace, const char *_destFile) {

// handle album cover image request
static void handleCoverImageRequest(AsyncWebServerRequest *request) {
if (!gFSystem.exists("/.cover")) {
if (!gPlayProperties.coverFileName) {
// empty image:
// request->send(200, "image/svg+xml", "<?xml version=\"1.0\"?><svg xmlns=\"http://www.w3.org/2000/svg\"/>");
if (gPlayProperties.isWebstream) {
if (gPlayProperties.playMode == WEBSTREAM) {
// no cover -> send placeholder icon for webstream (fa-soundcloud)
snprintf(Log_Buffer, Log_BufferLength, "no cover image for webstream");
Log_Println(Log_Buffer, LOGLEVEL_NOTICE);
Expand All @@ -1152,18 +1157,17 @@ static void handleCoverImageRequest(AsyncWebServerRequest *request) {
return;
}

File coverFile = gFSystem.open("/.cover", FILE_READ);

// skip 1 byte encoding
coverFile.seek(1);
File coverFile = gFSystem.open(gPlayProperties.coverFileName, FILE_READ);
// seek to start position, skip 1 byte encoding
coverFile.seek(gPlayProperties.coverFilePos + 1);
// mime-type (null terminated)
char mimeType[255];
for (uint8_t i = 0u; i < 255; i++) {
mimeType[i] = coverFile.read();
if (uint8_t(mimeType[i]) == 0)
break;
}
snprintf(Log_Buffer, Log_BufferLength, "serve cover image (%s)", (char *) mimeType);
snprintf(Log_Buffer, Log_BufferLength, "serve cover image (%s): %s", (char *) mimeType, gPlayProperties.coverFileName);
Log_Println(Log_Buffer, LOGLEVEL_NOTICE);

// skip image type (1 Byte)
Expand All @@ -1174,7 +1178,7 @@ static void handleCoverImageRequest(AsyncWebServerRequest *request) {
break;
}

int imageSize = coverFile.size() - coverFile.position();
int imageSize = gPlayProperties.coverFileSize - coverFile.position();

AsyncWebServerResponse *response = request->beginResponse(
mimeType,
Expand All @@ -1187,6 +1191,8 @@ static void handleCoverImageRequest(AsyncWebServerRequest *request) {
file.close();
Log_Println("cover image serving finished, close file", LOGLEVEL_DEBUG);
}
// do not consume too much cpu time
vTaskDelay(portTICK_RATE_MS * 50u);
return max(0, bytes); // return 0 even when no bytes were loaded
}
);
Expand Down