Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
409
Src/replicant/nswasabi/PlaybackBase.cpp
Normal file
409
Src/replicant/nswasabi/PlaybackBase.cpp
Normal file
|
@ -0,0 +1,409 @@
|
|||
#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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue