123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409 |
- #include "PlaybackBase.h"
- #include <stdlib.h>
- #include <assert.h>
- #ifdef __ANDROID__
- #include <android/log.h> // TODO: replace with generic logging API
- #else
- #define ANDROID_LOG_INFO 0
- #define ANDROID_LOG_ERROR 1
- static void __android_log_print(int, const char *, const char *, ...)
- {
- }
- #endif
- PlaybackBase::PlaybackBase()
- {
- wake_flags=0;
- last_wake_flags=0;
- playback_thread=0;
- secondary_parameters=0;
- filename=0;
- player=0;
- queued_seek=0;
- output_service=0;
- }
- int PlaybackBase::Initialize(nx_uri_t filename, ifc_player *player)
- {
- this->player = player;
- this->filename = NXURIRetain(filename);
- return NErr_Success;
- }
- PlaybackBase::~PlaybackBase()
- {
- if (secondary_parameters)
- secondary_parameters->Release();
- if (filename)
- NXURIRelease(filename);
- if (queued_seek)
- free(queued_seek);
- if (playback_thread)
- NXThreadJoin(playback_thread, 0);
- }
- int PlaybackBase::Playback_Play(svc_output *output, ifc_playback_parameters *secondary_parameters)
- {
- if (!playback_thread)
- return 1;
- __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Play");
- output_service = output;
- threadloop_node_t *apc = thread_loop.GetAPC();
- if (apc)
- {
- this->secondary_parameters = secondary_parameters;
- if (secondary_parameters)
- secondary_parameters->Retain();
- apc->func = APC_Play;
- apc->param1 = this;
- thread_loop.Schedule(apc);
- return NErr_Success;
- }
- else
- return NErr_OutOfMemory;
- }
- int PlaybackBase::Playback_SeekSeconds(double seconds)
- {
- __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Seek (%f seconds)", seconds);
- Agave_Seek *seek = (Agave_Seek *)malloc(sizeof(Agave_Seek));
- if (seek)
- {
- seek->position_type = AGAVE_PLAYPOSITION_SECONDS;
- seek->position.seconds = seconds;
- threadloop_node_t *apc = thread_loop.GetAPC();
- if (apc)
- {
- apc->func = APC_Seek;
- apc->param1 = this;
- apc->param2 = seek;
- thread_loop.Schedule(apc);
- return NErr_Success;
- }
- }
- free(seek);
- return NErr_OutOfMemory;
- }
- int PlaybackBase::Playback_Pause()
- {
- __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Pause");
- threadloop_node_t *apc = thread_loop.GetAPC();
- if (apc)
- {
- apc->func = APC_Pause;
- apc->param1 = this;
- thread_loop.Schedule(apc);
- return NErr_Success;
- }
- else
- return NErr_OutOfMemory;
- }
- int PlaybackBase::Playback_Unpause()
- {
- __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Unpause");
- threadloop_node_t *apc = thread_loop.GetAPC();
- if (apc)
- {
- apc->func = APC_Unpause;
- apc->param1 = this;
- thread_loop.Schedule(apc);
- return NErr_Success;
- }
- else
- return NErr_OutOfMemory;
- }
- int PlaybackBase::Playback_Stop()
- {
- __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Stop");
- threadloop_node_t *apc = thread_loop.GetAPC();
- if (apc)
- {
- apc->func = APC_Stop;
- apc->param1 = this;
- thread_loop.Schedule(apc);
- return NErr_Success;
- }
- else
- return NErr_OutOfMemory;
- }
- int PlaybackBase::Playback_Close()
- {
- __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Close");
- threadloop_node_t *apc = thread_loop.GetAPC();
- if (apc)
- {
- apc->func = APC_Close;
- apc->param1 = this;
- thread_loop.Schedule(apc);
- return NErr_Success;
- }
- else
- return NErr_OutOfMemory;
- }
- int PlaybackBase::FileLockCallback_Interrupt()
- {
- __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] Interrupt");
- threadloop_node_t *apc = thread_loop.GetAPC();
- if (apc)
- {
- apc->func = APC_Interrupt;
- apc->param1 = this;
- thread_loop.Schedule(apc);
- return NErr_Success;
- }
- else
- return NErr_OutOfMemory;
- }
- void PlaybackBase::ToggleFlags(int wake_reason)
- {
- switch(wake_reason)
- {
- case WAKE_KILL:
- last_wake_flags ^= WAKE_KILL; /* toggle kill flag */
- break;
- case WAKE_STOP:
- last_wake_flags ^= WAKE_STOP; /* toggle stop flag */
- break;
- case WAKE_PLAY:
- last_wake_flags ^= WAKE_PLAY; /* toggle play flag */
- break;
- case WAKE_PAUSE:
- case WAKE_UNPAUSE:
- last_wake_flags ^= WAKE_PAUSE; /* toggle pause flag */
- break;
- case WAKE_INTERRUPT:
- last_wake_flags ^= WAKE_INTERRUPT; /* toggle interrupt flag */
- break;
- }
- }
- int PlaybackBase::WakeReason(int mask) const
- {
- int reason_awoken = last_wake_flags ^ wake_flags;
- reason_awoken = reason_awoken & mask;
- if (reason_awoken & WAKE_INTERRUPT)
- {
- if (wake_flags & WAKE_INTERRUPT)
- return WAKE_INTERRUPT;
- else
- return WAKE_RESUME;
- }
- if (reason_awoken & WAKE_STOP)
- {
- return WAKE_STOP;
- }
- if (reason_awoken & WAKE_KILL)
- {
- return WAKE_KILL;
- }
- if (reason_awoken & WAKE_PLAY)
- {
- if (wake_flags & WAKE_PLAY)
- return WAKE_PLAY;
- else /* if someone cleared the play flag for whatever reason, just treat it as a 0 */
- return 0;
- }
- if (reason_awoken & WAKE_PAUSE)
- {
- if (wake_flags & WAKE_PAUSE)
- return WAKE_PAUSE;
- else
- return WAKE_UNPAUSE;
- }
- return 0;
- }
- int PlaybackBase::Wake(int mask)
- {
- assert(mask != 0); /* make sure they didn't specify a 0 mask (which would make this function potentially never return */
- assert((mask & WAKE_ALL_MASK) != 0); /* make sure it's a valid mask */
- for (;;)
- {
- int reason_awoken = last_wake_flags ^ wake_flags;
- reason_awoken = reason_awoken & mask;
- if (reason_awoken)
- {
- int ret = WakeReason(mask);
- ToggleFlags(ret); // mark the last-known-state of the wake flags
- return ret;
- }
- if (((mask & WAKE_PLAY) && !(wake_flags & WAKE_PLAY))/* if we're stopped and they asked to be woken up for play */
- || ((mask & WAKE_PAUSE) && (wake_flags & WAKE_PAUSE)) /* or waiting to be woken up for unpause */
- || ((mask & WAKE_INTERRUPT) && (wake_flags & WAKE_INTERRUPT))) /* or waiting to be woken up for resume */
- {
- thread_loop.Step();
- int ret = WakeReason(mask);
- if (ret) /* if ret is !0, it means we gotten woken up for a reason we care about */
- {
- ToggleFlags(ret); // mark the last-known-state of the wake flags
- return ret;
- }
- }
- else /* no reason to sleep, so just return 0 (no change) */
- {
- return 0;
- }
- }
- }
- int PlaybackBase::Check(int mask)
- {
- assert(mask != 0); /* make sure they didn't specify a 0 mask (which would make this function potentially never return */
- assert((mask & WAKE_ALL_MASK) != 0); /* make sure it's a valid mask */
- int reason_awoken = last_wake_flags ^ wake_flags;
- reason_awoken = reason_awoken & mask;
- int ret = 0;
- if (reason_awoken)
- {
- ret = WakeReason(mask);
- ToggleFlags(ret); // mark the last-known-state of the wake flags
- }
- return ret;
- }
- int PlaybackBase::Wait(unsigned int milliseconds, int mask)
- {
- int reason_awoken = last_wake_flags ^ wake_flags;
- reason_awoken = reason_awoken & mask;
- if (reason_awoken)
- {
- int ret = WakeReason(mask);
- ToggleFlags(ret); // mark the last-known-state of the wake flags
- return ret;
- }
- thread_loop.Step(milliseconds);
- int ret = WakeReason(mask);
- ToggleFlags(ret); // mark the last-known-state of the wake flags
- return ret;
- }
- int PlaybackBase::Sleep(unsigned int milliseconds, int mask)
- {
- int reason_awoken = last_wake_flags ^ wake_flags;
- reason_awoken = reason_awoken & mask;
- if (reason_awoken)
- {
- int ret = WakeReason(mask);
- assert(ret != 0);
- return ret;
- }
- thread_loop.Step(milliseconds);
- int ret = WakeReason(mask);
- return ret;
- }
- void PlaybackBase::OnStopPlaying()
- {
- // turn off the play flag (also adjust old wake flags so we don't trigger a WAKE_STOP)
- __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] OnStopPlaying");
- wake_flags &= ~WAKE_PLAY;
- last_wake_flags &= ~WAKE_PLAY;
- }
- void PlaybackBase::OnInterrupted()
- {
- __android_log_print(ANDROID_LOG_INFO, "libreplicant", "[PlaybackBase] OnInterrupted");
- wake_flags &= ~WAKE_INTERRUPT;
- last_wake_flags &= ~WAKE_INTERRUPT;
- }
- Agave_Seek *PlaybackBase::GetSeek()
- {
- Agave_Seek *seek = queued_seek;
- queued_seek=0;
- return seek;
- }
- void PlaybackBase::FreeSeek(Agave_Seek *seek)
- {
- free(seek);
- }
- bool PlaybackBase::PendingSeek()
- {
- return !!queued_seek;
- }
- void PlaybackBase::APC_Play(void *_playback_base, void *param2, double real_value)
- {
- PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
- playback_base->wake_flags |= WAKE_PLAY;
- }
- void PlaybackBase::APC_Seek(void *_playback_base, void *_seek, double real_value)
- {
- PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
- Agave_Seek *seek = (Agave_Seek *)_seek;
- free(playback_base->queued_seek);
- playback_base->queued_seek = seek;
- }
- void PlaybackBase::APC_Pause(void *_playback_base, void *param2, double real_value)
- {
- PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
- playback_base->wake_flags |= WAKE_PAUSE;
- }
- void PlaybackBase::APC_Unpause(void *_playback_base, void *param2, double real_value)
- {
- PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
- playback_base->wake_flags &= ~WAKE_PAUSE;
- }
- void PlaybackBase::APC_Stop(void *_playback_base, void *param2, double real_value)
- {
- PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
- playback_base->wake_flags |= WAKE_STOP;
- }
- void PlaybackBase::APC_Close(void *_playback_base, void *param2, double real_value)
- {
- PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
- playback_base->wake_flags |= WAKE_KILL;
- }
- void PlaybackBase::APC_Interrupt(void *_playback_base, void *param2, double real_value)
- {
- PlaybackBase *playback_base = (PlaybackBase *)_playback_base;
- playback_base->wake_flags |= WAKE_INTERRUPT;
- }
|