removed codecs to save memory

This commit is contained in:
2025-07-06 21:25:41 +02:00
parent 6022655198
commit fe04474ed8
104 changed files with 64077 additions and 0 deletions

View File

@@ -0,0 +1,287 @@
/*
* index.h
*
* Created on: 13.12.2022
* Updated on: 20.12.2022
* Author: Wolle
*
* ESP32 - DLNA
*
*/
#ifndef INDEX_H_
#define INDEX_H_
#include "Arduino.h"
// file in raw data format for PROGMEM
const char index_html[] PROGMEM = R"=====(
<!DOCTYPE HTML>
<html>
<head>
<title>ESP32 - DLNA</title>
<style type="text/css"> /* optimized with csstidy */
html { /* This is the groundplane */
font-family : serif;
height : 100%;
font-size: 16px;
color : DarkSlateGray;
background-color : navy;
margin : 0;
padding : 0;
}
#content {
min-height : 540px;
min-width : 725px;
overflow : hidden;
background-color : lightskyblue;
margin : 0;
padding : 5px;
}
#tab-content1 {
margin : 20px;
}
.boxstyle {
height : 36px;
padding-top : 0;
padding-left : 15px;
padding-bottom : 0;
background-color: white;
font-size : 16px;
line-height : normal;
border-color: black;
border-style: solid;
border-width: thin;
border-radius : 5px;
}
#BODY { display:block; }
</style>
</head>
<script>
// global variables and functions
// ---- websocket section------------------------
var socket = undefined
var host = location.hostname
var tm
function ping() {
if (socket.readyState == 1) { // reayState 'open'
socket.send("ping")
console.log("send ping")
tm = setTimeout(function () {
console.log('The connection to the ESP32 is interrupted! Please reload the page!')
}, 10000)
}
}
function connect() {
socket = new WebSocket('ws://'+window.location.hostname+':81/');
socket.onopen = function () {
console.log("Websocket connected")
socket.send('DLNA_getServer')
setInterval(ping, 20000)
};
socket.onclose = function (e) {
console.log(e)
console.log('Socket is closed. Reconnect will be attempted in 1 second.', e)
socket = null
setTimeout(function () {
connect()
}, 1000)
}
socket.onerror = function (err) {
console.log(err)
}
socket.onmessage = function(event) {
var socketMsg = event.data
var n = socketMsg.indexOf('=')
var msg = ''
var val = ''
if (n >= 0) {
var msg = socketMsg.substring(0, n)
var val = socketMsg.substring(n + 1)
// console.log("para ",msg, " val ",val)
}
else {
msg = socketMsg
}
switch(msg) {
case "pong": clearTimeout(tm)
break
case "DLNA_Names": showServer(val)
break
case "Level1": show_DLNA_Content(val, 1)
break
case "Level2": show_DLNA_Content(val, 2)
break
case "Level3": show_DLNA_Content(val, 3)
break
case "Level4": show_DLNA_Content(val, 4)
break
case "Level5": show_DLNA_Content(val, 5)
break
default: console.log('unknown message', msg, val)
}
}
}
// ---- end websocket section------------------------
document.addEventListener('readystatechange', event => {
if (event.target.readyState === 'interactive') { // same as: document.addEventListener('DOMContentLoaded'...
// same as jQuery.ready
console.log('All HTML DOM elements are accessible')
// document.getElementById('dialog').style.display = 'none' // hide the div (its only a template)
}
if (event.target.readyState === 'complete') {
console.log('Now external resources are loaded too, like css,src etc... ')
connect(); // establish websocket connection
}
})
function showServer(val){
console.log(val)
var select = document.getElementById('server')
select.options.length = 0;
var server = val.split(",")
for (i = -1; i < (server.length); i++) {
opt = document.createElement('OPTION')
if(i == -1){
opt.value = ""
opt.text = "Select a DLNA Server here"
}
else{
console.log(server[i])
opt.value = server[i]
opt.text = server[i]
}
select.add(opt)
}
}
function show_DLNA_Content(val, level){
var select
if(level == 1) select = document.getElementById('level1')
if(level == 2) select = document.getElementById('level2')
if(level == 3) select = document.getElementById('level3')
if(level == 4) select = document.getElementById('level4')
if(level == 5) select = document.getElementById('level5')
content =JSON.parse(val)
//console.log(ct[1].name)
select.options.length = 0;
for (i = -1; i < (content.length); i++) {
opt = document.createElement('OPTION')
if(i == -1){
opt.value = ""
opt.text = "Select level " + level.toString()
}
else{
var n
var c
if(content[i].isDir == true){
n = content[i].name.concat('\xa0\xa0', '<DIR>'); // more than one space
c = 'D=' + content[i].id // is directory
}
else{
n = content[i].name + '\xa0\xa0' + content[i].size;
c = 'F=' + content[i].id // is file
}
opt.value = c
opt.text = n
}
select.add(opt)
}
}
function selectserver (presctrl) { // preset, select a server, root, level0
socket.send('DLNA_getContent0=' + presctrl.value)
select = document.getElementById('level1'); select.options.length = 0; // clear next level
select = document.getElementById('level2'); select.options.length = 0;
select = document.getElementById('level3'); select.options.length = 0;
select = document.getElementById('level4'); select.options.length = 0;
select = document.getElementById('level5'); select.options.length = 0;
console.log('DLNA_getContent0=' + presctrl.value)
}
function select_l1 (presctrl) { // preset, select root
socket.send('DLNA_getContent1=' + presctrl.value)
select = document.getElementById('level2'); select.options.length = 0; // clear next level
select = document.getElementById('level3'); select.options.length = 0;
select = document.getElementById('level4'); select.options.length = 0;
select = document.getElementById('level5'); select.options.length = 0;
console.log('DLNA_getContent1=' + presctrl.value)
}
function select_l2 (presctrl) { // preset, select level 1
socket.send('DLNA_getContent2=' + presctrl.value)
select = document.getElementById('level3'); select.options.length = 0;
select = document.getElementById('level4'); select.options.length = 0;
select = document.getElementById('level5'); select.options.length = 0;
console.log('DLNA_getContent2=' + presctrl.value)
}
function select_l3 (presctrl) { // preset, select level 2
socket.send('DLNA_getContent3=' + presctrl.value)
select = document.getElementById('level4'); select.options.length = 0;
select = document.getElementById('level5'); select.options.length = 0;
console.log('DLNA_getContent3=' + presctrl.value)
}
function select_l4 (presctrl) { // preset, select level 3
socket.send('DLNA_getContent4=' + presctrl.value)
select = document.getElementById('level5'); select.options.length = 0;
console.log('DLNA_getContent4=' + presctrl.value)
}
function select_l5 (presctrl) { // preset, select level 4
socket.send('DLNA_getContent5=' + presctrl.value)
console.log('DLNA_getContent5=' + presctrl.value)
}
</script>
<body id="BODY">
<!--==============================================================================================-->
<div id="content">
<div id="content1">
<div style="font-size: 50px; text-align: center; flex: 1;">
ESP32 - DLNA
</div>
<div style="display: flex;">
<div style="flex: 0 0 calc(100% - 0px);">
<select class="boxstyle" style="width: 100%;" onchange="selectserver(this)" id="server">
<option value="-1">Select a DLNA Server here</option>
</select>
<select class="boxstyle" style="width: 100%; margin-top: 5px;" onchange="select_l1(this)" id="level1">
<option value="-1"> </option>
</select>
<select class="boxstyle" style="width: 100%; margin-top: 5px;" onchange="select_l2(this)" id="level2">
<option value="-1"> </option>
</select>
<select class="boxstyle" style="width: 100%; margin-top: 5px;" onchange="select_l3(this)" id="level3">
<option value="-1"> </option>
</select>
<select class="boxstyle" style="width: 100%; margin-top: 5px;" onchange="select_l4(this)" id="level4">
<option value="-1"> </option>
</select>
<select class="boxstyle" style="width: 100%; margin-top: 5px;" onchange="select_l5(this)" id="level5">
<option value="-1"> </option>
</select>
</div>
</div>
<hr>
</div>
</div>
<!--==============================================================================================-->
</body>
</html>
)=====";
#endif /* INDEX_H_ */

View File

@@ -0,0 +1,189 @@
#include <Arduino.h>
#include <WiFi.h>
#include "websrv.h"
#include "index.h"
#include "Audio.h"
#include "SoapESP32.h"
#include "Arduino_JSON.h"
#include <vector>
using namespace std;
#define I2S_DOUT 25
#define I2S_BCLK 27
#define I2S_LRC 26
char SSID[] = "xxxxx";
char PASS[] = "xxxxx";
WebSrv webSrv;
WiFiClient client;
WiFiUDP udp;
SoapESP32 soap(&client, &udp);
Audio audio;
uint numServers = 0;
int currentServer = -1;
uint32_t media_downloadPort = 0;
String media_downloadIP = "";
vector<String> names{};
//----------------------------------------------------------------------------------------------------------------------
int DLNA_setCurrentServer(String serverName){
int serverNum = -1;
for(int i = 0; i < names.size(); i++){
if(names[i] == serverName) serverNum = i;
}
currentServer = serverNum;
return serverNum;
}
void DLNA_showServer(){ // Show connection details of all discovered, usable media servers
String msg = "DLNA_Names=";
soapServer_t srv;
names.clear();
for(int i = 0; i < numServers; i++){
soap.getServerInfo(i, &srv);
Serial.printf("Server[%d]: IP address: %s port: %d name: %s -> controlURL: %s\n",
i, srv.ip.toString().c_str(), srv.port, srv.friendlyName.c_str(), srv.controlURL.c_str());
msg += srv.friendlyName;
if(i < numServers - 1) msg += ',';
names.push_back(srv.friendlyName);
}
log_i("msg %s", msg.c_str());
webSrv.send(msg);
}
void DLNA_browseServer(String objectId, uint8_t level){
JSONVar myObject;
soapObjectVect_t browseResult;
soapObject_t object;
// Here the user selects the DLNA server whose content he wants to see, level 0 is root
if(level == 0){
if(DLNA_setCurrentServer(objectId) < 0) {log_e("DLNA Server not found"); return;}
objectId = "0";
}
soap.browseServer(currentServer, objectId.c_str(), &browseResult);
if(browseResult.size() == 0){
log_i("no content!"); // then the directory is empty
return;
}
log_v("objectID: %s", objectId.c_str());
for (int i = 0; i < browseResult.size(); i++){
object = browseResult[i];
myObject[i]["name"]= object.name;
myObject[i]["isDir"] = object.isDirectory;
if(object.isDirectory){
myObject[i]["id"] = object.id;
}
else {
myObject[i]["id"] = object.uri;
media_downloadPort = object.downloadPort;
media_downloadIP = object.downloadIp.toString();
}
myObject[i]["size"] = (uint32_t)object.size;
myObject[i]["uri"] = object.id;
log_v("objectName %s", browseResult[i].name.c_str());
log_v("objectId %s", browseResult[i].artist.c_str());
}
level++;
String msg = "Level" + String(level,10) + "=" + JSON.stringify(myObject);
log_v("msg = %s", msg.c_str());
webSrv.send(msg);
browseResult.clear();
}
void DLNA_getFileItems(String uri){
soapObjectVect_t browseResult;
log_v("uri: %s", uri.c_str());
log_v("downloadIP: %s", media_downloadIP.c_str());
log_v("downloadport: %d", media_downloadPort);
String URL = "http://" + media_downloadIP + ":" + media_downloadPort + "/" + uri;
log_i("URL=%s", URL.c_str());
audio.connecttohost(URL.c_str());
}
void DLNA_showContent(String objectId, uint8_t level){
log_v("obkId=%s", objectId.c_str());
if(level == 0){
DLNA_browseServer(objectId, level);
}
if(objectId.startsWith("D=")) {
objectId = objectId.substring(2);
DLNA_browseServer(objectId, level);
}
if(objectId.startsWith("F=")) {
objectId = objectId.substring(2);
DLNA_getFileItems(objectId);
}
}
//----------------------------------------------------------------------------------------------------------------------
// S E T U P
//----------------------------------------------------------------------------------------------------------------------
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(SSID, PASS);
while (WiFi.status() != WL_CONNECTED) delay(1500);
log_i("connected, IP=%s", WiFi.localIP().toString().c_str());
webSrv.begin(80, 81); // HTTP port, WebSocket port
soap.seekServer();
numServers = soap.getServerCount();
audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
audio.setVolume(21); // 0...21
}
//----------------------------------------------------------------------------------------------------------------------
// L O O P
//----------------------------------------------------------------------------------------------------------------------
void loop() {
vTaskDelay(1);
if(webSrv.loop()) return; // if true: ignore all other for faster response to web
audio.loop();
}
//----------------------------------------------------------------------------------------------------------------------
// E V E N T S
//----------------------------------------------------------------------------------------------------------------------
void WEBSRV_onCommand(const String cmd, const String param, const String arg){ // called from html
log_d("WS_onCmd: cmd=\"%s\", params=\"%s\", arg=\"%s\"", cmd.c_str(),param.c_str(), arg.c_str());
if(cmd == "index.html"){ webSrv.show(index_html); return;}
if(cmd == "ping"){webSrv.send("pong"); return;}
if(cmd == "favicon.ico") return;
if(cmd == "DLNA_getServer") {DLNA_showServer(); return;}
if(cmd == "DLNA_getContent0"){DLNA_showContent(param, 0); return;}
if(cmd == "DLNA_getContent1"){DLNA_showContent(param, 1); return;} // search for level 1 content
if(cmd == "DLNA_getContent2"){DLNA_showContent(param, 2); return;} // search for level 2 content
if(cmd == "DLNA_getContent3"){DLNA_showContent(param, 3); return;} // search for level 3 content
if(cmd == "DLNA_getContent4"){DLNA_showContent(param, 4); return;} // search for level 4 content
if(cmd == "DLNA_getContent5"){DLNA_showContent(param, 5); return;} // search for level 5 content
log_e("unknown HTMLcommand %s, param=%s", cmd.c_str(), param.c_str());
}
void WEBSRV_onRequest(const String request, uint32_t contentLength){
log_d("WS_onReq: %s contentLength %d", request.c_str(), contentLength);
if(request.startsWith("------")) return; // uninteresting WebKitFormBoundaryString
if(request.indexOf("form-data") > 0) return; // uninteresting Info
log_e("unknown request: %s",request.c_str());
}
void WEBSRV_onInfo(const char* info){
log_v("HTML_info: %s", info); // infos for debug
}
void audio_info(const char *info){
Serial.print("info "); Serial.println(info);
}
void audio_id3data(const char *info){ //id3 metadata
Serial.print("id3data ");Serial.println(info);
}
void audio_eof_stream(const char* info){ // The webstream comes to an end
Serial.print("end of stream: ");Serial.println(info);
}
void audio_bitrate(const char *info){
Serial.print("bitrate ");Serial.println(info);
}
void audio_lasthost(const char *info){ //stream URL played
Serial.print("lasthost ");Serial.println(info);
}