From 94489618cacb4782d5cf7c3069e96b932dfba4c9 Mon Sep 17 00:00:00 2001 From: Fabian Schlenz Date: Wed, 20 Nov 2019 05:04:27 +0100 Subject: [PATCH] Moved reading of SD card data into a dedicated class DataSource. --- include/data_sources.h | 34 ++++++++++++++++++++++++++++++++++ include/player.h | 4 ++-- src/data_sources.cpp | 35 +++++++++++++++++++++++++++++++++++ src/player.cpp | 41 +++++++++-------------------------------- 4 files changed, 80 insertions(+), 34 deletions(-) create mode 100644 include/data_sources.h create mode 100644 src/data_sources.cpp diff --git a/include/data_sources.h b/include/data_sources.h new file mode 100644 index 0000000..2649e1d --- /dev/null +++ b/include/data_sources.h @@ -0,0 +1,34 @@ +#pragma once + +#include +#include +#include "config.h" + +class DataSource { +private: +public: + DataSource() {}; + ~DataSource() {}; + virtual size_t read(uint8_t* buf, size_t len) = 0; + virtual uint8_t read() = 0; + virtual size_t position() = 0; + virtual void seek(size_t position) = 0; + virtual size_t size() = 0; + virtual void close() = 0; + virtual void skip_id3_tag(); +}; + +class SDDataSource : public DataSource { +private: + File _file; +public: + SDDataSource(String file); + ~SDDataSource(); + size_t read(uint8_t* buf, size_t len); + uint8_t read(); + size_t position(); + void seek(size_t position); + size_t size(); + void close(); + void skip_id3_tag(); +}; diff --git a/include/player.h b/include/player.h index a35478b..522ee20 100644 --- a/include/player.h +++ b/include/player.h @@ -4,6 +4,7 @@ #include #include "spi_master.h" #include "playlist.h" +#include "data_sources.h" class Player; @@ -55,7 +56,6 @@ private: void _flush_and_cancel(); int8_t _get_endbyte(); void _flush(uint count, int8_t fill_byte); - uint32_t _id3_tag_offset(File f); void _play_file(String filename, uint32_t offset); void _finish_playing(); void _finish_stopping(bool turn_speaker_off); @@ -72,7 +72,7 @@ private: SPISettings _spi_settings_fast = SPISettings(4000000, MSBFIRST, SPI_MODE0); SPISettings* _spi_settings = &_spi_settings_slow; - File _file; + DataSource* _file; uint32_t _file_size = 0; uint8_t _buffer[32]; uint32_t _current_play_position = 0; diff --git a/src/data_sources.cpp b/src/data_sources.cpp new file mode 100644 index 0000000..281b0bf --- /dev/null +++ b/src/data_sources.cpp @@ -0,0 +1,35 @@ +#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(); } + +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); + } +} diff --git a/src/player.cpp b/src/player.cpp index 7f4286c..463bc55 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -545,8 +545,8 @@ bool Player::play() { void Player::_play_file(String file, uint32_t file_offset) { INFO("play_file('%s', %d)\n", file.c_str(), file_offset); _spi->select_sd(); - _file = SD.open(file); - _file_size = _file.size(); + _file = new SDDataSource(file); + _file_size = _file->size(); _spi->select_sd(false); if (!_file) { DEBUG("Could not open file %s", file.c_str()); @@ -561,10 +561,10 @@ void Player::_play_file(String file, uint32_t file_offset) { _spi->select_sd(); if (file_offset == 0) { - _file.seek(_id3_tag_offset(_file)); + _file->skip_id3_tag(); } _refills = 0; - _current_play_position = _file.position(); + _current_play_position = _file->position(); _spi->select_sd(false); _skip_to = file_offset; if (_skip_to>0) _mute(); @@ -573,30 +573,6 @@ void Player::_play_file(String file, uint32_t file_offset) { _controller->send_player_status(); } -uint32_t Player::_id3_tag_offset(File f) { - uint32_t original_position = f.position(); - uint32_t offset = 0; - if (f.read()=='I' && f.read()=='D' && f.read()=='3') { - DEBUG("ID3 tag found\n"); - // Skip ID3 tag version - f.read(); f.read(); - byte tags = f.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 & f.read()); - } - offset += 10; - if (footer_present) offset += 10; - DEBUG("ID3 tag length is %d bytes.\n", offset); - } else { - DEBUG("No ID3 tag found\n"); - } - f.seek(original_position); - return offset; -} - void Player::_flush(uint count, int8_t byte) { _spi->select_vs1053_xdcs(); SPI.beginTransaction(*_spi_settings); @@ -652,7 +628,8 @@ void Player::_finish_stopping(bool turn_speaker_off) { _state = idle; _stopped_at = millis(); if (_file) { - _file.close(); + _file->close(); + delete _file; } _current_play_position = 0; _file_size = 0; @@ -664,7 +641,7 @@ void Player::_refill() { _spi->select_sd(); _refills++; if (_refills % 1000 == 0) DEBUG("."); - uint8_t result = _file.read(_buffer, sizeof(_buffer)); + uint8_t result = _file->read(_buffer, sizeof(_buffer)); _spi->select_sd(false); if (result == 0) { // File is over. @@ -686,13 +663,13 @@ void Player::_refill() { _write_data(_buffer); if (_skip_to > 0) { - if (_skip_to > _file.position()) { + if (_skip_to > _file->position()) { uint16_t status = _read_control_register(SCI_STATUS); if ((status & SS_DO_NOT_JUMP) == 0) { DEBUG("Skipping to %d.\n", _skip_to); _flush(2048, _get_endbyte()); _spi->select_sd(); - _file.seek(_skip_to); + _file->seek(_skip_to); _spi->select_sd(false); _skip_to = 0; _unmute();