Moved reading of SD card data into a dedicated class DataSource.
This commit is contained in:
parent
82d8f07eea
commit
94489618ca
34
include/data_sources.h
Normal file
34
include/data_sources.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <SD.h>
|
||||||
|
#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();
|
||||||
|
};
|
@ -4,6 +4,7 @@
|
|||||||
#include <SD.h>
|
#include <SD.h>
|
||||||
#include "spi_master.h"
|
#include "spi_master.h"
|
||||||
#include "playlist.h"
|
#include "playlist.h"
|
||||||
|
#include "data_sources.h"
|
||||||
|
|
||||||
class Player;
|
class Player;
|
||||||
|
|
||||||
@ -55,7 +56,6 @@ private:
|
|||||||
void _flush_and_cancel();
|
void _flush_and_cancel();
|
||||||
int8_t _get_endbyte();
|
int8_t _get_endbyte();
|
||||||
void _flush(uint count, int8_t fill_byte);
|
void _flush(uint count, int8_t fill_byte);
|
||||||
uint32_t _id3_tag_offset(File f);
|
|
||||||
void _play_file(String filename, uint32_t offset);
|
void _play_file(String filename, uint32_t offset);
|
||||||
void _finish_playing();
|
void _finish_playing();
|
||||||
void _finish_stopping(bool turn_speaker_off);
|
void _finish_stopping(bool turn_speaker_off);
|
||||||
@ -72,7 +72,7 @@ private:
|
|||||||
SPISettings _spi_settings_fast = SPISettings(4000000, MSBFIRST, SPI_MODE0);
|
SPISettings _spi_settings_fast = SPISettings(4000000, MSBFIRST, SPI_MODE0);
|
||||||
SPISettings* _spi_settings = &_spi_settings_slow;
|
SPISettings* _spi_settings = &_spi_settings_slow;
|
||||||
|
|
||||||
File _file;
|
DataSource* _file;
|
||||||
uint32_t _file_size = 0;
|
uint32_t _file_size = 0;
|
||||||
uint8_t _buffer[32];
|
uint8_t _buffer[32];
|
||||||
uint32_t _current_play_position = 0;
|
uint32_t _current_play_position = 0;
|
||||||
|
35
src/data_sources.cpp
Normal file
35
src/data_sources.cpp
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -545,8 +545,8 @@ bool Player::play() {
|
|||||||
void Player::_play_file(String file, uint32_t file_offset) {
|
void Player::_play_file(String file, uint32_t file_offset) {
|
||||||
INFO("play_file('%s', %d)\n", file.c_str(), file_offset);
|
INFO("play_file('%s', %d)\n", file.c_str(), file_offset);
|
||||||
_spi->select_sd();
|
_spi->select_sd();
|
||||||
_file = SD.open(file);
|
_file = new SDDataSource(file);
|
||||||
_file_size = _file.size();
|
_file_size = _file->size();
|
||||||
_spi->select_sd(false);
|
_spi->select_sd(false);
|
||||||
if (!_file) {
|
if (!_file) {
|
||||||
DEBUG("Could not open file %s", file.c_str());
|
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();
|
_spi->select_sd();
|
||||||
if (file_offset == 0) {
|
if (file_offset == 0) {
|
||||||
_file.seek(_id3_tag_offset(_file));
|
_file->skip_id3_tag();
|
||||||
}
|
}
|
||||||
_refills = 0;
|
_refills = 0;
|
||||||
_current_play_position = _file.position();
|
_current_play_position = _file->position();
|
||||||
_spi->select_sd(false);
|
_spi->select_sd(false);
|
||||||
_skip_to = file_offset;
|
_skip_to = file_offset;
|
||||||
if (_skip_to>0) _mute();
|
if (_skip_to>0) _mute();
|
||||||
@ -573,30 +573,6 @@ void Player::_play_file(String file, uint32_t file_offset) {
|
|||||||
_controller->send_player_status();
|
_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) {
|
void Player::_flush(uint count, int8_t byte) {
|
||||||
_spi->select_vs1053_xdcs();
|
_spi->select_vs1053_xdcs();
|
||||||
SPI.beginTransaction(*_spi_settings);
|
SPI.beginTransaction(*_spi_settings);
|
||||||
@ -652,7 +628,8 @@ void Player::_finish_stopping(bool turn_speaker_off) {
|
|||||||
_state = idle;
|
_state = idle;
|
||||||
_stopped_at = millis();
|
_stopped_at = millis();
|
||||||
if (_file) {
|
if (_file) {
|
||||||
_file.close();
|
_file->close();
|
||||||
|
delete _file;
|
||||||
}
|
}
|
||||||
_current_play_position = 0;
|
_current_play_position = 0;
|
||||||
_file_size = 0;
|
_file_size = 0;
|
||||||
@ -664,7 +641,7 @@ void Player::_refill() {
|
|||||||
_spi->select_sd();
|
_spi->select_sd();
|
||||||
_refills++;
|
_refills++;
|
||||||
if (_refills % 1000 == 0) DEBUG(".");
|
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);
|
_spi->select_sd(false);
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
// File is over.
|
// File is over.
|
||||||
@ -686,13 +663,13 @@ void Player::_refill() {
|
|||||||
_write_data(_buffer);
|
_write_data(_buffer);
|
||||||
|
|
||||||
if (_skip_to > 0) {
|
if (_skip_to > 0) {
|
||||||
if (_skip_to > _file.position()) {
|
if (_skip_to > _file->position()) {
|
||||||
uint16_t status = _read_control_register(SCI_STATUS);
|
uint16_t status = _read_control_register(SCI_STATUS);
|
||||||
if ((status & SS_DO_NOT_JUMP) == 0) {
|
if ((status & SS_DO_NOT_JUMP) == 0) {
|
||||||
DEBUG("Skipping to %d.\n", _skip_to);
|
DEBUG("Skipping to %d.\n", _skip_to);
|
||||||
_flush(2048, _get_endbyte());
|
_flush(2048, _get_endbyte());
|
||||||
_spi->select_sd();
|
_spi->select_sd();
|
||||||
_file.seek(_skip_to);
|
_file->seek(_skip_to);
|
||||||
_spi->select_sd(false);
|
_spi->select_sd(false);
|
||||||
_skip_to = 0;
|
_skip_to = 0;
|
||||||
_unmute();
|
_unmute();
|
||||||
|
Loading…
Reference in New Issue
Block a user