removed codecs to save memory
This commit is contained in:
287
lib/ESP32-audioI2S/examples/DLNA/src/index.h
Normal file
287
lib/ESP32-audioI2S/examples/DLNA/src/index.h
Normal 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_ */
|
||||
189
lib/ESP32-audioI2S/examples/DLNA/src/main.cpp
Normal file
189
lib/ESP32-audioI2S/examples/DLNA/src/main.cpp
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user