#include "data_sources.h" ////////////// SDDataSource ////////////// SDDataSource::SDDataSource(String file) { _file = SD.open(file, "r"); } SDDataSource::~SDDataSource() { if (_file) _file.close(); } size_t SDDataSource::read(uint8_t* buf, size_t len) { return _file.read(buf, len); } uint8_t SDDataSource::read() { return _file.read(); } size_t SDDataSource::position() { return _file.position(); } void SDDataSource::seek(size_t position) { _file.seek(position); } size_t SDDataSource::size() { return _file.size(); } void SDDataSource::close() { _file.close(); } bool SDDataSource::usable() { return _file; } void SDDataSource::skip_id3_tag() { uint32_t original_position = _file.position(); uint32_t offset = 0; if (_file.read()=='I' && _file.read()=='D' && _file.read()=='3') { DEBUG("ID3 tag found\n"); // Skip ID3 tag version _file.read(); _file.read(); byte tags = _file.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 & _file.read()); } offset += 10; if (footer_present) offset += 10; DEBUG("ID3 tag length is %d bytes.\n", offset); _file.seek(offset); } else { DEBUG("No ID3 tag found\n"); _file.seek(original_position); } } ////////////// HTTPSDataSource ////////////// HTTPSDataSource::HTTPSDataSource(String url, uint32_t offset) { uint8_t tries_left = 5; int status; do { if (tries_left == 0) { ERROR("Redirection loop? Cancelling!\n"); return; } tries_left--; DEBUG("Connecting to %s...\n", url.c_str()); if (_http) delete _http; _http = new HTTPClient(); const char* headers[] = {"location"}; _http->collectHeaders(headers, 1); bool result = _http->begin(url); DEBUG("HTTP->begin result: %d\n", result); if (!result) return; status = _http->GET(); DEBUG("Status code: %d\n", status); if (status == HTTP_CODE_FOUND || status==HTTP_CODE_MOVED_PERMANENTLY || status==HTTP_CODE_TEMPORARY_REDIRECT) { if (_http->hasHeader("Location")) { url = _http->header("Location"); } else if (_http->hasHeader("location")) { url = _http->header("location"); } else { ERROR("Got redirection HTTP code, but could not find Location header.\n"); for(int i=0; i<_http->headers(); i++) { DEBUG(" Header: %s=%s\n", _http->headerName(i).c_str(), _http->header(i).c_str()); } return; } } else if (status != HTTP_CODE_OK) { DEBUG("Unexpected HTTP return code. Cancelling.\n"); return; } } while (status != HTTP_CODE_OK); _length = _http->getSize(); DEBUG("Content-Length: %d\n", _length); _stream = _http->getStreamPtr(); } HTTPSDataSource::~HTTPSDataSource() { if (_stream) _stream->stop(); _http->end(); delete _stream; delete _http; } bool HTTPSDataSource::usable() { return _http && _stream; } size_t HTTPSDataSource::read(uint8_t* buf, size_t len) { size_t result = _stream->read(buf, len); _position += result; return result; } uint8_t HTTPSDataSource::read() { _position++; return _stream->read(); } size_t HTTPSDataSource::position() { return _position; } void HTTPSDataSource::seek(size_t position) { return; /* TODO */ } size_t HTTPSDataSource::size() { return _length; } void HTTPSDataSource::close() { _stream->stop(); }