Refactor!
This commit is contained in:
parent
5d7a343a20
commit
a5f4d7149a
14 changed files with 13024 additions and 1920 deletions
203
LibraryViewer/private/Player.cpp
Normal file
203
LibraryViewer/private/Player.cpp
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
#include "Player.hpp"
|
||||
#include "Buffer.hpp"
|
||||
#include "Multithreading.hpp"
|
||||
|
||||
#include "portaudio.h"
|
||||
|
||||
class DeviceStream {
|
||||
friend class Player;
|
||||
|
||||
public:
|
||||
DeviceStream() {
|
||||
auto paStatus = Pa_Initialize() ;
|
||||
mInitializationStatus = paStatus == paNoError;
|
||||
if (!mInitializationStatus) {
|
||||
fprintf(stderr, "An error occurred while using the portaudio stream\n");
|
||||
fprintf(stderr, "Error number: %d\n", paStatus);
|
||||
fprintf(stderr, "Error message: %s\n", Pa_GetErrorText(paStatus));
|
||||
}
|
||||
}
|
||||
|
||||
~DeviceStream() {
|
||||
if (mInitializationStatus) {
|
||||
Pa_Terminate();
|
||||
}
|
||||
}
|
||||
|
||||
bool openStream(const tp::halnf* buffer, const tp::ualni* pointerMax, tp::ualni sampleRate) {
|
||||
if (!mInitializationStatus) return false;
|
||||
|
||||
mPointerMax = pointerMax;
|
||||
mBuffer = buffer;
|
||||
|
||||
PaStreamParameters outputParameters;
|
||||
|
||||
outputParameters.device = Pa_GetDefaultOutputDevice();
|
||||
if (outputParameters.device == paNoDevice) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const PaDeviceInfo* pInfo = Pa_GetDeviceInfo(outputParameters.device);
|
||||
if (pInfo != 0) {
|
||||
printf("Output device name: '%s'\r", pInfo->name);
|
||||
}
|
||||
|
||||
outputParameters.channelCount = 2;
|
||||
outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output */
|
||||
outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputParameters.device)->defaultLowOutputLatency;
|
||||
outputParameters.hostApiSpecificStreamInfo = NULL;
|
||||
|
||||
PaError err = Pa_OpenStream(&mPaStream, NULL, &outputParameters, sampleRate, 44100 * 0.2f, 0, &DeviceStream::paCallback, this);
|
||||
|
||||
if (err != paNoError) {
|
||||
return false;
|
||||
}
|
||||
|
||||
err = Pa_SetStreamFinishedCallback(mPaStream, &DeviceStream::paStreamFinished);
|
||||
|
||||
if (err != paNoError) {
|
||||
Pa_CloseStream(mPaStream);
|
||||
mPaStream = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool closeStream() {
|
||||
if (mPaStream == 0) return false;
|
||||
PaError err = Pa_CloseStream(mPaStream);
|
||||
|
||||
mPaStream = 0;
|
||||
mBuffer = nullptr;
|
||||
mPointerMax = 0;
|
||||
mPointer = 0;
|
||||
|
||||
return (err == paNoError);
|
||||
}
|
||||
|
||||
bool continueStream() {
|
||||
if (mPaStream == 0) return false;
|
||||
PaError err = Pa_StartStream(mPaStream);
|
||||
return (err == paNoError);
|
||||
}
|
||||
|
||||
bool freezeStream() {
|
||||
if (mPaStream == 0) return false;
|
||||
PaError err = Pa_StopStream(mPaStream);
|
||||
return (err == paNoError);
|
||||
}
|
||||
|
||||
tp::ualni getCurrentFrame() const {
|
||||
return mPointer;
|
||||
}
|
||||
|
||||
void setCurrentFrame(tp::ualni ptr) {
|
||||
ptr = tp::clamp(ptr, (tp::ualni) 0, *mPointerMax);
|
||||
mMutex.lock();
|
||||
mPointer = ptr;
|
||||
mMutex.unlock();
|
||||
}
|
||||
|
||||
private:
|
||||
int paCallbackMethod(const void* inputBuffer, void* outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags) {
|
||||
if (mPointer + framesPerBuffer >= *mPointerMax) return paContinue;
|
||||
|
||||
float* out = (float*) outputBuffer;
|
||||
mMutex.lock();
|
||||
for (unsigned long i = 0; i < framesPerBuffer; i++) {
|
||||
*out++ = (mBuffer)[mPointer * 2] * mVolume;
|
||||
*out++ = (mBuffer)[mPointer * 2 + 1] * mVolume;
|
||||
mPointer++;
|
||||
}
|
||||
mMutex.unlock();
|
||||
return paContinue;
|
||||
}
|
||||
|
||||
void paStreamFinishedMethod() { printf("Stream Completed\n"); }
|
||||
|
||||
static int paCallback(const void* inputBuffer, void* outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void* userData) {
|
||||
return ((DeviceStream*) userData)->paCallbackMethod(inputBuffer, outputBuffer, framesPerBuffer, timeInfo, statusFlags);
|
||||
}
|
||||
|
||||
static void paStreamFinished(void* userData) { return ((DeviceStream*) userData)->paStreamFinishedMethod(); }
|
||||
|
||||
private:
|
||||
bool mInitializationStatus = false;
|
||||
PaStream* mPaStream = nullptr;
|
||||
tp::Mutex mMutex;
|
||||
|
||||
const tp::halnf* mBuffer = nullptr;
|
||||
const tp::ualni* mPointerMax = nullptr;
|
||||
|
||||
tp::ualni mPointer = 0;
|
||||
tp::halnf mVolume = 1.f;
|
||||
};
|
||||
|
||||
Player::Player() {
|
||||
mDeviceStream = new DeviceStream();
|
||||
}
|
||||
|
||||
Player::~Player() {
|
||||
delete mDeviceStream;
|
||||
}
|
||||
|
||||
bool Player::startStreamTrack(SongId id) {
|
||||
mDeviceStream->closeStream();
|
||||
|
||||
if (!mMusicStream.openStream(id)) {
|
||||
connected = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mDeviceStream->openStream(mMusicStream.getBuffer(), mMusicStream.getProgressLive(), mMusicStream.getRate())) {
|
||||
connected = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
mMusicStream.continueStream();
|
||||
|
||||
connected = id;
|
||||
return true;
|
||||
}
|
||||
|
||||
SongId Player::getPlayingId() const {
|
||||
return connected;
|
||||
}
|
||||
|
||||
void Player::continuePlayback() {
|
||||
if (!connected) return;
|
||||
mDeviceStream->continueStream();
|
||||
}
|
||||
|
||||
void Player::freezePlayback() {
|
||||
if (!connected) return;
|
||||
mDeviceStream->freezeStream();
|
||||
}
|
||||
|
||||
tp::halnf Player::getPlaybackProgress() const {
|
||||
if (!connected) return 0;
|
||||
return (tp::halnf) mDeviceStream->getCurrentFrame() / (tp::halnf) mMusicStream.getFramesLength();
|
||||
}
|
||||
|
||||
tp::halnf Player::getDurationSec() const { return 0; }
|
||||
|
||||
void Player::setPlaybackProgress(tp::halnf val) {
|
||||
if (!connected) return;
|
||||
mDeviceStream->setCurrentFrame(val * mMusicStream.getFramesLength());
|
||||
}
|
||||
|
||||
void Player::setVolume(tp::halnf vol) {
|
||||
if (!connected) return;
|
||||
mDeviceStream->mVolume = vol;
|
||||
}
|
||||
|
||||
tp::halnf Player::getLoadProgress() const {
|
||||
if (!connected) return 0;
|
||||
return (tp::halnf) mMusicStream.getFramesLoaded() / (tp::halnf) mMusicStream.getFramesLength();
|
||||
}
|
||||
|
||||
tp::halnf Player::getVolume() {
|
||||
if (!connected) return 0;
|
||||
return mDeviceStream->mVolume;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue