winamp/Src/replicant/nswasabi/PlaybackBase2.h
2024-09-24 14:54:57 +02:00

78 lines
3.0 KiB
C++

#pragma once
#include "PlaybackBase.h"
#include "foundation/error.h"
#include "service/api_service.h"
/* this one does most of the work for you.
It assumes blocking I/O and, generally, a simple implementation
You provide an implementation of PlaybackImpl */
class PlaybackBase2;
class PlaybackImpl
{
public:
void Connect(PlaybackBase2 *playback, ifc_playback_parameters *playback_parameters);
/* stuff you need to implement */
/* destructor. be diligent about closing stuff, can't guarantee that Close() got called beforehand */
virtual ~PlaybackImpl();
virtual ns_error_t Open(nx_uri_t filename)=0;
/* you need to handle the possibility that Close gets called more than one time */
virtual void Close()=0;
virtual bool IsSeekable()=0;
/* implementation note: add a reference (Retain) before assigning the value */
virtual ns_error_t GetMetadata(ifc_metadata **metadata)=0;
/* if you set *exact=false, GetLength will get called after the next DecodeStep */
virtual ns_error_t GetLength(double *length, bool *exact)=0;
/* only return an error if you're in a state you can't recover from.
if you can't seek, then just don't seek and return NErr_Success */
virtual ns_error_t Seek(const Agave_Seek *seek, ns_error_t *seek_error, double *new_position)=0;
/* return NErr_Success to continue
NErr_EndOfFile to indicate a natural end of file
otherwise return an error */
virtual ns_error_t DecodeStep()=0;
/* Save information and close the OS file handle.
fill resume_information with whatever information you'll need to resume */
virtual ns_error_t Interrupt(Agave_Seek *resume_information)=0;
/* During resume, be sure to call player->SetMetadata again */
virtual ns_error_t Resume(Agave_Seek *resume_information)=0;
protected:
PlaybackBase2 *playback;
ifc_playback_parameters *playback_parameters;
PlaybackImpl();
};
class PlaybackBase2 : public PlaybackBase
{
public:
PlaybackBase2();
~PlaybackBase2();
ns_error_t Initialize(api_service *service_manager, PlaybackImpl *implementation, nx_uri_t filename, ifc_player *player);
/* this two should ONLY be called from within your DecodeStep function! */
ns_error_t OpenOutput(const ifc_audioout::Parameters *parameters); // if this returns an error, return it from DecodeStep()
ns_error_t Output(const void *audio_data, size_t audio_data_length, double begin_position_seconds); // if this returns an error, return it from DecodeStep()
ns_error_t OutputNonInterleaved(const void *audio_data, size_t audio_data_length, double begin_position_seconds); // if this returns an error, return it from DecodeStep()
private:
static nx_thread_return_t NXTHREADCALL PlayerThreadFunction(nx_thread_parameter_t param);
nx_thread_return_t NXTHREADCALL DecodeLoop();
ns_error_t Init();
ns_error_t WaitForClose();
ns_error_t OutputWait();
ns_error_t Internal_Interrupt();
PlaybackImpl *implementation;
api_filelock *filelocker;
ifc_audioout *out;
bool paused;
double last_position;
bool exact_length;
ifc_audioout::Parameters parameters;
const uint8_t **output_pointers;
};