aboutsummaryrefslogtreecommitdiff
path: root/Src/replicant/nswasabi/PlaybackBase.h
diff options
context:
space:
mode:
authorJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
committerJef <jef@targetspot.com>2024-09-24 08:54:57 -0400
commit20d28e80a5c861a9d5f449ea911ab75b4f37ad0d (patch)
tree12f17f78986871dd2cfb0a56e5e93b545c1ae0d0 /Src/replicant/nswasabi/PlaybackBase.h
parent537bcbc86291b32fc04ae4133ce4d7cac8ebe9a7 (diff)
downloadwinamp-20d28e80a5c861a9d5f449ea911ab75b4f37ad0d.tar.gz
Initial community commit
Diffstat (limited to 'Src/replicant/nswasabi/PlaybackBase.h')
-rw-r--r--Src/replicant/nswasabi/PlaybackBase.h91
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);
+
+};