diff options
Diffstat (limited to 'Src/replicant/nswasabi/PlaybackBase.h')
-rw-r--r-- | Src/replicant/nswasabi/PlaybackBase.h | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/Src/replicant/nswasabi/PlaybackBase.h b/Src/replicant/nswasabi/PlaybackBase.h new file mode 100644 index 00000000..8a27387c --- /dev/null +++ b/Src/replicant/nswasabi/PlaybackBase.h @@ -0,0 +1,91 @@ +#pragma once +#include "nx/nx.h" +#include "nu/LockFreeItem.h" +#include "player/ifc_playback.h" +#include "player/ifc_player.h" +#include "player/svc_output.h" +#include "nu/ThreadLoop.h" +#include "filelock/api_filelock.h" + +/* TODO: we can probably redo this without the mutex, possibly using semaphores */ +class PlaybackBase : public ifc_playback, public cb_filelock +{ +public: + using ifc_playback::Retain; + using ifc_playback::Release; + + + /* ifc_playback implementation */ + int WASABICALL Playback_Play(svc_output *output, ifc_playback_parameters *secondary_parameters); + int WASABICALL Playback_SeekSeconds(double seconds); + int WASABICALL Playback_Pause(); + int WASABICALL Playback_Unpause(); + int WASABICALL Playback_Stop(); + int WASABICALL Playback_Close(); + + /* cb_filelock implementation */ + int WASABICALL FileLockCallback_Interrupt(); +protected: + nx_thread_t playback_thread; + svc_output *output_service; + ifc_player *player; + ifc_playback_parameters *secondary_parameters; + nx_uri_t filename; + + enum + { + WAKE_KILL=(1<<0), + WAKE_PLAY=(1<<1), + WAKE_PAUSE=(1<<2), + WAKE_STOP=(1<<3), + WAKE_INTERRUPT=(1<<4), + WAKE_UNPAUSE=(1<<5), // this is actually unused in wake_flags, just used as a return value from Wake/WakeReason + WAKE_RESUME=(1<<6), // this is actually unused in wake_flags, just used as a return value from Wake/WakeReason + WAKE_START_MASK = WAKE_PLAY|WAKE_STOP, + WAKE_KILL_MASK = WAKE_KILL|WAKE_STOP, + WAKE_ALL_MASK = WAKE_KILL|WAKE_PLAY|WAKE_PAUSE|WAKE_STOP|WAKE_INTERRUPT, + }; + + +protected: + PlaybackBase(); + ~PlaybackBase(); + + /* === API for derived classes to use === */ + int Initialize(nx_uri_t filename, ifc_player *player); + int Init(); + + /* this checks if one of the flags in mask has toggled. + if playback is stopped and WAKE_PLAY is in the mask, this will sleep until a flag changes + if playback is paused and WAKE_PAUSE is in the mask, this will sleep until a flag changes + if both WAKE_PLAY and WAKE_PAUSE are in the mask, this will sleep until either happens + returns 0 if no flag changed */ + int Wake(int mask); /* Sleeps indefinitely until a flag changes */ + int Check(int mask); /* like Wake() but never actually goes to sleep for any reason */ + int Wait(unsigned int milliseconds, int mask); /* Sleeps for a limited amount of time for a flag to change */ + int Sleep(unsigned int milliseconds, int mask); /* unlike Wait, this one does *not* update last flags */ + int WakeReason(int mask) const; + + void OnInterrupted(); /* turn off the WAKE_INTERRUPT flag */ + void OnStopPlaying(); /* turn off the WAKE_PLAY flag */ + bool PendingSeek(); + Agave_Seek *GetSeek(); + void FreeSeek(Agave_Seek *seek); + /* === End of API for derived classes to use === */ +private: + void ToggleFlags(int wake_reason); + + int wake_flags; /* marked volatile so the compiler doesn't cache */ + int last_wake_flags; + Agave_Seek *queued_seek; + + ThreadLoop thread_loop; + static void APC_Play(void *_playback_base, void *param2, double real_value); + static void APC_Seek(void *_playback_base, void *param2, double real_value); + static void APC_Pause(void *_playback_base, void *param2, double real_value); + static void APC_Unpause(void *_playback_base, void *param2, double real_value); + static void APC_Stop(void *_playback_base, void *param2, double real_value); + static void APC_Close(void *_playback_base, void *param2, double real_value); + static void APC_Interrupt(void *_playback_base, void *param2, double real_value); + +}; |