diff options
Diffstat (limited to 'Src/replicant/nswasabi/PlaybackBase2.h')
-rw-r--r-- | Src/replicant/nswasabi/PlaybackBase2.h | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/Src/replicant/nswasabi/PlaybackBase2.h b/Src/replicant/nswasabi/PlaybackBase2.h new file mode 100644 index 00000000..5743aa53 --- /dev/null +++ b/Src/replicant/nswasabi/PlaybackBase2.h @@ -0,0 +1,78 @@ +#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; +};
\ No newline at end of file |