Add Database and refactor player/playback

Add Database class with SQLite fetch/fetchAlbum methods. Refactor
PlaybackEngine (data callback, seek, getPosition, decoder lifecycle)
and Player API (PlaybackEngine member, queue handling, PlayerLocal).
Update Metadata::Track fields to include artist/title/album/trackNr/length.
This commit is contained in:
2026-06-20 15:19:34 +02:00
parent 2130d95ed5
commit 80bffc0fdd
11 changed files with 315 additions and 104 deletions
+54 -42
View File
@@ -3,61 +3,73 @@
#include <memory>
#include <stdexcept>
using PE = PlaybackEngine;
PE::PlaybackEngine(){
PE::PlaybackEngine () {
configureDecoder();
configureDevice();
}
PE::~PlaybackEngine() {
ma_device_uninit( &device_);
ma_decoder_uninit( &state.decoder );
PE::~PlaybackEngine () {
ma_device_uninit ( &device_ );
ma_decoder_uninit ( &state.decoder );
}
void PE::data_callback( ma_device* pDevice, void* pOutput, const void*, ma_uint32 frameCount ){
std::unique_ptr<PlaybackState> state = std::unique_ptr<PlaybackState> ( static_cast<PlaybackState*>( pDevice->pUserData ));
ma_uint64 framesRead = 0;
ma_result result = ma_decoder_read_pcm_frames( &state->decoder, pOutput, frameCount, &framesRead );
if ( result != MA_SUCCESS || framesRead < frameCount ) { state->finished.store(true); }
};
void PE::data_callback ( ma_device *pDevice, void *pOutput, const void *, ma_uint32 frameCount ) {
std::unique_ptr<PlaybackState> state =
std::unique_ptr<PlaybackState> ( static_cast<PlaybackState *> ( pDevice->pUserData ) );
ma_uint64 framesRead = 0;
ma_result result = ma_decoder_read_pcm_frames ( &state->decoder, pOutput, frameCount, &framesRead );
if ( result != MA_SUCCESS || framesRead < frameCount ) {
state->finished.store ( true );
}
};
void PE::configureDevice() {
ma_device_config deviceConfig = ma_device_config_init( ma_device_type_playback );
void PE::configureDevice () {
ma_device_config deviceConfig = ma_device_config_init ( ma_device_type_playback );
deviceConfig.playback.format = state.decoder.outputFormat;
deviceConfig.playback.channels = state.decoder.outputChannels;
deviceConfig.sampleRate = state.decoder.outputSampleRate;
deviceConfig.dataCallback = PE::data_callback;
deviceConfig.pUserData = &state;
}
deviceConfig.playback.format = state.decoder.outputFormat;
deviceConfig.playback.channels = state.decoder.outputChannels;
deviceConfig.sampleRate = state.decoder.outputSampleRate;
deviceConfig.dataCallback = PE::data_callback;
deviceConfig.pUserData = &state;
}
void PE::configureDecoder(){
ma_decoder_config decoderConfig = ma_decoder_config_init( format_, 0, sampleRate_ );
}
void PE::configureDecoder () { ma_decoder_config decoderConfig = ma_decoder_config_init ( format_, 0, sampleRate_ ); }
void PE::initDevice(){
if ( ma_device_init( nullptr, &deviceConfig, &device_ ) != MA_SUCCESS ) {
throw std::runtime_error( "failed to open file.");
}
}
void PE::initDecoder( const char* filePath ) {
if ( ma_decoder_init_file( filePath, &decoderConfig, &state.decoder) != MA_SUCCESS ){
throw std::runtime_error( "Failed to open {filePath}.");
void PE::initDevice () {
if ( ma_device_init ( nullptr, &deviceConfig, &device_ ) != MA_SUCCESS ) {
throw std::runtime_error ( "failed to open file." );
}
}
void PE::startPlayback(){
//ma_decoder_init_file( filePath, &decoderConfig, &decoder );
if ( ma_device_start( &device_ ) != MA_SUCCESS ) {
throw std::runtime_error( "Failed to start playback device.\n");
ma_device_uninit( &device_ );
ma_decoder_uninit( &state.decoder );
}
}
void PE::initDecoder ( const char *filePath ) {
if ( ma_decoder_init_file ( filePath, &decoderConfig, &state.decoder ) != MA_SUCCESS ) {
throw std::runtime_error ( "Failed to open {filePath}." );
}
}
void PE::stopPlayback() {
ma_device_stop( &device_ );
}
void PE::uninitDecoder() {
ma_decoder_uninit( &state.decoder );
}
void PE::startPlayback () {
// ma_decoder_init_file( filePath, &decoderConfig, &decoder );
if ( ma_device_start ( &device_ ) != MA_SUCCESS ) {
throw std::runtime_error ( "Failed to start playback device.\n" );
ma_device_uninit ( &device_ );
ma_decoder_uninit ( &state.decoder );
}
}
void PE::stopPlayback () { ma_device_stop ( &device_ ); }
void PE::seek ( ma_uint64 frame ) {
auto decoder = state.decoder;
ma_decoder_seek_to_pcm_frame ( &state.decoder, frame );
}
auto PE::getPosition () {
ma_decoder_get_cursor_in_pcm_frames ( &state.decoder, &cursor_ );
return cursor_;
}