diff --git a/include/data_sources.h b/include/data_sources.h index d65e591..8f19dfe 100644 --- a/include/data_sources.h +++ b/include/data_sources.h @@ -41,6 +41,8 @@ private: WiFiClient* _stream = NULL; HTTPClientWrapper* _http = NULL; uint32_t _position; + String _url; + void _init(String url, uint32_t offset); public: HTTPSDataSource(String url, uint32_t offset=0); ~HTTPSDataSource(); @@ -51,4 +53,6 @@ public: size_t size(); void close(); bool usable(); + int peek(int offset=0); + void skip_id3_tag(); }; diff --git a/include/http_client_wrapper.h b/include/http_client_wrapper.h index a80e15f..9f4d127 100644 --- a/include/http_client_wrapper.h +++ b/include/http_client_wrapper.h @@ -34,4 +34,5 @@ public: uint32_t getSize(); String readUntil(String sep); String readLine(); + int peek(int offset=0); }; diff --git a/src/data_sources.cpp b/src/data_sources.cpp index 0fb4337..0c8ff78 100644 --- a/src/data_sources.cpp +++ b/src/data_sources.cpp @@ -39,6 +39,12 @@ void SDDataSource::skip_id3_tag() { ////////////// HTTPSDataSource ////////////// HTTPSDataSource::HTTPSDataSource(String url, uint32_t offset) { + _url = url; + _init(url, offset); +} + +void HTTPSDataSource::_init(String url, uint32_t offset) { + _url = url; _http = new HTTPClientWrapper(); if (!_http->get(url, offset)) return; _position = 0; @@ -52,6 +58,31 @@ bool HTTPSDataSource::usable() { return _http; } size_t HTTPSDataSource::read(uint8_t* buf, size_t len) { size_t result = _http->read(buf, len); _position += result; return result; } int HTTPSDataSource::read() { int b = _http->read(); if (b>=0) _position++; return b; } size_t HTTPSDataSource::position() { return _position; } -void HTTPSDataSource::seek(size_t position) { return; /* TODO */ } +void HTTPSDataSource::seek(size_t position) { _http->close(); delete _http; _init(_url, position); } size_t HTTPSDataSource::size() { return _http->getSize(); } void HTTPSDataSource::close() { _http->close(); } +int HTTPSDataSource::peek(int offset) { return _http->peek(offset); } + +void HTTPSDataSource::skip_id3_tag() { + uint32_t offset = 0; + if (_http->peek(0)=='I' && _http->peek(1)=='D' && _http->peek(2)=='3') { + DEBUG("ID3 tag found\n"); + // Skip ID3 tag marker + _http->read(); _http->read(); _http->read(); + // Skip ID3 tag version + _http->read(); _http->read(); + byte tags = _http->read(); + bool footer_present = tags & 0x10; + DEBUG("ID3 footer found: %d\n", footer_present); + for (byte i=0; i<4; i++) { + offset <<= 7; + offset |= (0x7F & _http->read()); + } + offset += 10; + if (footer_present) offset += 10; + DEBUG("ID3 tag length is %d bytes.\n", offset); + seek(offset); + } else { + DEBUG("No ID3 tag found\n"); + } +} diff --git a/src/http_client_wrapper.cpp b/src/http_client_wrapper.cpp index bb1a90a..0e00e95 100644 --- a/src/http_client_wrapper.cpp +++ b/src/http_client_wrapper.cpp @@ -211,3 +211,12 @@ String HTTPClientWrapper::readUntil(String sep) { String HTTPClientWrapper::readLine() { return readUntil("\n\r"); } + +int HTTPClientWrapper::peek(int offset) { + if (_buffer_position >= _buffer_length) _fill_buffer(); + + if (_buffer_position + offset < 0 || _buffer_position + offset >= _buffer_length) { + return -1; + } + return _buffer[_buffer_position + offset]; +} \ No newline at end of file