Compare commits

..

9 Commits

Author SHA1 Message Date
philippe44
29f71fc677 Merge branch 'master-v4.3' of https://github.com/sle118/squeezelite-esp32 into master-v4.3 2024-01-10 21:36:53 -08:00
philippe44
a14a6edc1b reset flac packet flag - release 2024-01-10 21:36:50 -08:00
github-actions
35bf0a3c10 Update prebuilt objects [skip actions] 2024-01-11 03:00:35 +00:00
philippe44
55a8658f3a OggFlac & displayer fixes (see CHANGELOG) - release 2024-01-10 18:58:47 -08:00
github-actions
b0d9e1668c Update prebuilt objects [skip actions] 2024-01-04 08:48:28 +00:00
philippe44
922367baf5 no false alarm on OggS miss + homogeneous use of u32/size_t/int - release 2024-01-04 00:46:36 -08:00
philippe44
01320db007 always copy granule unless it's -1 (not valid) 2024-01-03 23:47:00 -08:00
philippe44
f677695fc7 handle pages with no terminated packet 2024-01-03 23:25:08 -08:00
github-actions
7902af2bf0 Update prebuilt objects [skip actions] 2024-01-03 04:08:04 +00:00
28 changed files with 77 additions and 42 deletions

View File

@@ -1,3 +1,9 @@
2024-01-10
- add OggFlac to stream metadata
- fix OggFlac deadlock in flac callback when not enough data in streambuf
- fix no displayer due to threadshold too high (use 500ms instead)
- reset outputbuf when cspot starts
2024-01-01
- ogg stream are parsed to foward metadata to LMS
- fix some ogg parsing on multi-stream containers

View File

@@ -288,6 +288,7 @@ static bool raop_sink_cmd_handler(raop_event_t event, va_list args)
output.frames_played = 0;
output.external = DECODE_RAOP;
output.state = OUTPUT_STOPPED;
if (decode.state != DECODE_STOPPED) decode.state = DECODE_ERROR;
LOG_INFO("resizing buffer %u", outputbuf->size);
break;
@@ -377,6 +378,7 @@ static bool cspot_cmd_handler(cspot_event_t cmd, va_list args)
output.state = OUTPUT_STOPPED;
sink_state = SINK_ABORT;
_buf_flush(outputbuf);
_buf_limit(outputbuf, 0);
if (decode.state != DECODE_STOPPED) decode.state = DECODE_ERROR;
LOG_INFO("CSpot start track");
break;

View File

@@ -121,6 +121,9 @@ static FLAC__StreamDecoderReadStatus read_cb(const FLAC__StreamDecoder *decoder,
_buf_inc_readp(streambuf, bytes);
UNLOCK_S;
// give some time for stream to acquire data otherwise flac will hammer us
if (!end && !bytes) usleep(100 * 1000);
*want = bytes;
return end ? FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM : FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;

View File

@@ -139,8 +139,11 @@ static int _write_frames(frames_t out_frames, bool silence, s32_t gainL, s32_t g
u8_t *buf = silencebuf;
memcpy(btout + oframes * BYTES_PER_FRAME, buf, out_frames * BYTES_PER_FRAME);
}
output_visu_export(btout + oframes * BYTES_PER_FRAME, out_frames, output.current_sample_rate, silence, (gainL + gainR) / 2);
// don't update visu if we don't have enough data in buffer (500 ms)
if (silence || _buf_used(outputbuf) > BYTES_PER_FRAME * output.current_sample_rate / 2) {
output_visu_export(btout + oframes * BYTES_PER_FRAME, out_frames, output.current_sample_rate, silence, (gainL + gainR) / 2);
}
oframes += out_frames;

View File

@@ -485,8 +485,8 @@ static int _i2s_write_frames(frames_t out_frames, bool silence, s32_t gainL, s32
memcpy(obuf + oframes * BYTES_PER_FRAME, silencebuf, out_frames * BYTES_PER_FRAME);
}
// don't update visu if we don't have enough data in buffer
if (silence || output.external || _buf_used(outputbuf) > outputbuf->size >> 2 ) {
// don't update visu if we don't have enough data in buffer (500 ms)
if (silence || _buf_used(outputbuf) > BYTES_PER_FRAME * output.current_sample_rate / 2) {
output_visu_export(obuf + oframes * BYTES_PER_FRAME, out_frames, output.current_sample_rate, silence, (gainL + gainR) / 2);
}

View File

@@ -393,7 +393,9 @@ static void process_strm(u8_t *pkt, int len) {
stream_file(header, header_len, strm->threshold * 1024);
autostart -= 2;
} else {
stream_sock(ip, port, strm->format, header, header_len, strm->threshold * 1024, autostart >= 2);
stream_sock(ip, port, strm->flags & 0x20,
strm->format == 'o' || strm->format == 'u' || (strm->format == 'f' && strm->pcm_sample_size == 'o'),
header, header_len, strm->threshold * 1024, autostart >= 2);
}
sendSTAT("STMc", 0);
sentSTMu = sentSTMo = sentSTMl = false;

View File

@@ -585,7 +585,7 @@ struct streamstate {
void stream_init(log_level level, unsigned stream_buf_size);
void stream_close(void);
void stream_file(const char *header, size_t header_len, unsigned threshold);
void stream_sock(u32_t ip, u16_t port, char codec, const char *header, size_t header_len, unsigned threshold, bool cont_wait);
void stream_sock(u32_t ip, u16_t port, bool use_ssl, bool use_ogg, const char *header, size_t header_len, unsigned threshold, bool cont_wait);
bool stream_disconnect(void);
// decode.c

View File

@@ -62,8 +62,10 @@ static sockfd fd;
struct EXT_RAM_ATTR streamstate stream;
static EXT_RAM_ATTR struct {
bool flac;
enum { OGG_OFF, OGG_SYNC, OGG_HEADER, OGG_SEGMENTS, OGG_PAGE } state;
u32_t want, miss, match;
size_t want, miss, match;
u64_t granule;
u8_t* data, segments[255];
#pragma pack(push, 1)
struct {
@@ -128,7 +130,6 @@ static int _poll(SSL *ssl, struct pollfd *pollinfo, int timeout) {
}
#endif
static bool send_header(void) {
char *ptr = stream.header;
int len = stream.header_len;
@@ -177,12 +178,16 @@ static void _disconnect(stream_state state, disconnect_code disconnect) {
wake_controller();
}
static u32_t memfind(const u8_t* haystack, u32_t n, const char* needle, u32_t len, u32_t *offset) {
int i;
static size_t memfind(const u8_t* haystack, size_t n, const char* needle, size_t len, size_t* offset) {
size_t i;
for (i = 0; i < n && *offset != len; i++) *offset = (haystack[i] == needle[*offset]) ? *offset + 1 : 0;
return i;
}
/* https://xiph.org/ogg/doc/framing.html
* https://xiph.org/flac/ogg_mapping.html
* https://xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-610004.2 */
static void stream_ogg(size_t n) {
if (ogg.state == OGG_OFF) return;
u8_t* p = streambuf->writep;
@@ -204,7 +209,7 @@ static void stream_ogg(size_t n) {
if (consumed) break;
// we have to memorize position in case any of last 3 bytes match...
int pos = memfind(p, n, "OggS", 4, &ogg.match);
size_t pos = memfind(p, n, "OggS", 4, &ogg.match);
if (ogg.match == 4) {
consumed = pos - ogg.match;
ogg.state = OGG_HEADER;
@@ -212,7 +217,8 @@ static void stream_ogg(size_t n) {
ogg.data = (u8_t*) &ogg.header;
ogg.match = 0;
} else {
LOG_INFO("OggS not at expected position");
if (!ogg.match) LOG_INFO("OggS not at expected position %zu/%zu", pos, n);
LOG_INFO("OggS not at expected position %zu/%zu", pos, n);
return;
}
break;
@@ -229,10 +235,10 @@ static void stream_ogg(size_t n) {
break;
case OGG_SEGMENTS:
// calculate size of page using lacing values
for (int i = 0; i < ogg.want; i++) ogg.miss += ogg.data[i];
for (size_t i = 0; i < ogg.want; i++) ogg.miss += ogg.data[i];
ogg.want = ogg.miss;
if (ogg.header.granule == 0) {
if (ogg.header.granule == 0 || (ogg.header.granule == -1 && ogg.granule == 0)) {
// granule 0 means a new stream, so let's look into it
ogg.state = OGG_PAGE;
ogg.data = malloc(ogg.want);
@@ -241,17 +247,24 @@ static void stream_ogg(size_t n) {
ogg.state = OGG_SYNC;
ogg.data = NULL;
}
// memorize granule for next page
if (ogg.header.granule != -1) ogg.granule = ogg.header.granule;
break;
case OGG_PAGE: {
u32_t offset = 0;
char** tag = (char* []){ "\x3vorbis", "OpusTags", NULL };
size_t ofs = 0;
// try to find one of valid Ogg pattern (vorbis, opus)
for (char** tag = (char*[]) { "\x3vorbis", "OpusTags", NULL }; *tag; tag++, offset = 0) {
u32_t pos = memfind(ogg.data, ogg.want, *tag, strlen(*tag), &offset);
if (offset != strlen(*tag)) continue;
/* with OggFlac, we need the next page (packet) - VorbisComment is wrapped into a FLAC_METADATA
* and except with vorbis, comment packet starts a new page but even in vorbis, it won't span
* accross multiple pages */
if (ogg.flac) ofs = 4;
else if (!memcmp(ogg.data, "\x7f""FLAC", 5)) ogg.flac = true;
else for (size_t n = 0; *tag; tag++, ofs = 0) if ((ofs = memfind(ogg.data, ogg.want, *tag, strlen(*tag), &n)) && n == strlen(*tag)) break;
if (ofs) {
// u32:len,char[]:vendorId, u32:N, N x (u32:len,char[]:comment)
char* p = (char*) ogg.data + pos;
char* p = (char*) ogg.data + ofs;
p += *p + 4;
u32_t count = *p;
p += 4;
@@ -271,15 +284,17 @@ static void stream_ogg(size_t n) {
stream.header[stream.header_len++] = len;
memcpy(stream.header + stream.header_len, p, len);
stream.header_len += len;
LOG_INFO("metadata: %.*s", len, p);
}
}
ogg.flac = false;
stream.meta_send = true;
wake_controller();
LOG_INFO("Ogg metadata length: %u", stream.header_len - 3);
break;
}
free(ogg.data);
ogg.data = NULL;
ogg.state = OGG_SYNC;
break;
}
@@ -618,7 +633,7 @@ void stream_file(const char *header, size_t header_len, unsigned threshold) {
UNLOCK;
}
void stream_sock(u32_t ip, u16_t port, char codec, const char *header, size_t header_len, unsigned threshold, bool cont_wait) {
void stream_sock(u32_t ip, u16_t port, bool use_ssl, bool use_ogg, const char *header, size_t header_len, unsigned threshold, bool cont_wait) {
struct sockaddr_in addr;
#if EMBEDDED
@@ -719,7 +734,8 @@ void stream_sock(u32_t ip, u16_t port, char codec, const char *header, size_t he
stream.threshold = threshold;
ogg.miss = ogg.match = 0;
ogg.state = (codec == 'o' || codec == 'p') ? OGG_SYNC : OGG_OFF;
ogg.state = use_ogg ? OGG_SYNC : OGG_OFF;
ogg.flac = false;
UNLOCK;
}

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -74,6 +74,8 @@ declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getStatus(): {};
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
declare function getRadioButton(entry: any): string;
@@ -226,6 +228,7 @@ declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare function pushStatus(): void;
declare let sd: {};
declare let rf: boolean;
declare function refreshStatus(): void;

View File

@@ -1,5 +1,5 @@
target_add_binary_data( __idf_wifi-manager webapp/dist/css/index.4bbe29a78a667faa2b6f.css.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/favicon-32x32.png BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/index.html.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/index.c8ae2b.bundle.js.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/node_vendors.c8ae2b.bundle.js.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/index.baf383.bundle.js.gz BINARY)
target_add_binary_data( __idf_wifi-manager webapp/dist/js/node_vendors.baf383.bundle.js.gz BINARY)

View File

@@ -6,29 +6,29 @@ extern const uint8_t _favicon_32x32_png_start[] asm("_binary_favicon_32x32_png_s
extern const uint8_t _favicon_32x32_png_end[] asm("_binary_favicon_32x32_png_end");
extern const uint8_t _index_html_gz_start[] asm("_binary_index_html_gz_start");
extern const uint8_t _index_html_gz_end[] asm("_binary_index_html_gz_end");
extern const uint8_t _index_c8ae2b_bundle_js_gz_start[] asm("_binary_index_c8ae2b_bundle_js_gz_start");
extern const uint8_t _index_c8ae2b_bundle_js_gz_end[] asm("_binary_index_c8ae2b_bundle_js_gz_end");
extern const uint8_t _node_vendors_c8ae2b_bundle_js_gz_start[] asm("_binary_node_vendors_c8ae2b_bundle_js_gz_start");
extern const uint8_t _node_vendors_c8ae2b_bundle_js_gz_end[] asm("_binary_node_vendors_c8ae2b_bundle_js_gz_end");
extern const uint8_t _index_baf383_bundle_js_gz_start[] asm("_binary_index_baf383_bundle_js_gz_start");
extern const uint8_t _index_baf383_bundle_js_gz_end[] asm("_binary_index_baf383_bundle_js_gz_end");
extern const uint8_t _node_vendors_baf383_bundle_js_gz_start[] asm("_binary_node_vendors_baf383_bundle_js_gz_start");
extern const uint8_t _node_vendors_baf383_bundle_js_gz_end[] asm("_binary_node_vendors_baf383_bundle_js_gz_end");
const char * resource_lookups[] = {
"/css/index.4bbe29a78a667faa2b6f.css.gz",
"/favicon-32x32.png",
"/index.html.gz",
"/js/index.c8ae2b.bundle.js.gz",
"/js/node_vendors.c8ae2b.bundle.js.gz",
"/js/index.baf383.bundle.js.gz",
"/js/node_vendors.baf383.bundle.js.gz",
""
};
const uint8_t * resource_map_start[] = {
_index_4bbe29a78a667faa2b6f_css_gz_start,
_favicon_32x32_png_start,
_index_html_gz_start,
_index_c8ae2b_bundle_js_gz_start,
_node_vendors_c8ae2b_bundle_js_gz_start
_index_baf383_bundle_js_gz_start,
_node_vendors_baf383_bundle_js_gz_start
};
const uint8_t * resource_map_end[] = {
_index_4bbe29a78a667faa2b6f_css_gz_end,
_favicon_32x32_png_end,
_index_html_gz_end,
_index_c8ae2b_bundle_js_gz_end,
_node_vendors_c8ae2b_bundle_js_gz_end
_index_baf383_bundle_js_gz_end,
_node_vendors_baf383_bundle_js_gz_end
};

View File

@@ -1,6 +1,6 @@
/***********************************
webpack_headers
dist/css/index.4bbe29a78a667faa2b6f.css.gz,dist/favicon-32x32.png,dist/index.html.gz,dist/js/index.c8ae2b.bundle.js.gz,dist/js/node_vendors.c8ae2b.bundle.js.gz
dist/css/index.4bbe29a78a667faa2b6f.css.gz,dist/favicon-32x32.png,dist/index.html.gz,dist/js/index.baf383.bundle.js.gz,dist/js/node_vendors.baf383.bundle.js.gz
***********************************/
#pragma once
#include <inttypes.h>

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
server_certs/r2m01.cer.45 Normal file

Binary file not shown.

BIN
server_certs/r2m01.cer.46 Normal file

Binary file not shown.

BIN
server_certs/r2m01.cer.47 Normal file

Binary file not shown.