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:
+54
-42
@@ -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_;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user