219 lines
6.1 KiB
C++
219 lines
6.1 KiB
C++
/*************************************************************************/
|
|
/* File : WaveSeek.cpp */
|
|
/* */
|
|
/* Author : Leïla AIT KACI (www.noxaka.com) */
|
|
/* Last Modification : 15/09/07 */
|
|
/*************************************************************************/
|
|
#include "CKAll.h"
|
|
|
|
CKObjectDeclaration* FillBehaviorWaveSeekDecl ();
|
|
CKERROR CreateWaveSeekProto (CKBehaviorPrototype **);
|
|
int WaveSeek (const CKBehaviorContext& BehContext);
|
|
int WaveSeekCallback (const CKBehaviorContext& behcontext);
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Defines
|
|
//////////////////////////////////////////////////////////////////////
|
|
#define BB_NAME "Wave Seek"
|
|
#define BB_DESC "Seek in a Wave Sound File played with the Wave Player."
|
|
#define BB_CAT "Sounds/Basic"
|
|
#define BB_VERSION 0x00010000
|
|
#define BB_TARGET CKCID_WAVESOUND
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Enums for Parameter's Indexes
|
|
//////////////////////////////////////////////////////////////////////
|
|
enum BB_IN
|
|
{
|
|
IN_IN
|
|
};
|
|
|
|
enum BB_OUT
|
|
{
|
|
OUT_OUT
|
|
};
|
|
|
|
enum BB_PIN
|
|
{
|
|
PIN_TIME = 0,
|
|
PIN_PROGRESSION = 0
|
|
};
|
|
|
|
enum BB_LOC
|
|
{
|
|
SET_PROGRESSION
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CKObjectDeclaration *FillBehaviorWaveSeekDecl()
|
|
{
|
|
CKObjectDeclaration *od = CreateCKObjectDeclaration(BB_NAME);
|
|
od->SetType(CKDLL_BEHAVIORPROTOTYPE);
|
|
od->SetCompatibleClassId(BB_TARGET);
|
|
od->SetAuthorGuid(VIRTOOLS_GUID);
|
|
od->SetAuthorName("Virtools");
|
|
od->SetDescription(BB_DESC);
|
|
od->SetVersion(BB_VERSION);
|
|
od->SetCategory(BB_CAT);
|
|
od->SetGuid(CKGUID(0x43362343, 0x61f591b0));
|
|
od->SetCreationFunction(CreateWaveSeekProto);
|
|
|
|
return od;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
CKERROR CreateWaveSeekProto(CKBehaviorPrototype** pproto)
|
|
{
|
|
CKBehaviorPrototype *proto = CreateCKBehaviorPrototype(BB_NAME);
|
|
if (!proto) {
|
|
return CKERR_OUTOFMEMORY;
|
|
}
|
|
|
|
//---
|
|
proto->DeclareInput("In");
|
|
|
|
//---
|
|
proto->DeclareOutput("Out");
|
|
|
|
//----
|
|
proto->DeclareInParameter("Time", CKPGUID_TIME);
|
|
|
|
//----
|
|
proto->DeclareSetting("Use Progression", CKPGUID_BOOL, "FALSE");
|
|
|
|
proto->SetBehaviorFlags((CK_BEHAVIOR_FLAGS)(CKBEHAVIOR_TARGETABLE));
|
|
proto->SetBehaviorCallbackFct(WaveSeekCallback, CKCB_BEHAVIORSETTINGSEDITED);
|
|
proto->SetFunction(WaveSeek);
|
|
|
|
*pproto = proto;
|
|
return CK_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
int WaveSeek(const CKBehaviorContext& BehContext)
|
|
{
|
|
CKBehavior* beh = BehContext.Behavior;
|
|
CKContext* ctx = BehContext.Context;
|
|
|
|
//---
|
|
beh->ActivateInput(IN_IN, FALSE);
|
|
beh->ActivateOutput(OUT_OUT, TRUE);
|
|
|
|
//---
|
|
CKWaveSound* wav = (CKWaveSound*) beh->GetTarget();
|
|
if ( !wav )
|
|
return CKBR_OK;
|
|
|
|
//---
|
|
CKBOOL Playing = wav->IsPlaying();
|
|
|
|
//---
|
|
CKBOOL UseProgression;
|
|
beh->GetLocalParameterValue(SET_PROGRESSION, &UseProgression);
|
|
|
|
//---
|
|
float time = 0.0f;
|
|
if ( UseProgression ) {
|
|
float Progression = 0;
|
|
beh->GetInputParameterValue(PIN_PROGRESSION, &Progression);
|
|
time = Progression * wav->GetSoundLength();
|
|
}
|
|
else
|
|
beh->GetInputParameterValue(PIN_TIME, &time);
|
|
|
|
if ( time < 0 )
|
|
time = 0;
|
|
else if ( time > wav->GetSoundLength() ) {
|
|
wav->Stop(0);
|
|
return CKBR_OK;
|
|
}
|
|
|
|
//// Find the closest byte positioning in the file
|
|
int ByteTime = (DWORD) (time * (float) wav->m_WaveFormat.nAvgBytesPerSec / 1000.0f);
|
|
ByteTime -= ByteTime % wav->m_WaveFormat.nBlockAlign;
|
|
|
|
////
|
|
CKSoundManager* sm = (CKSoundManager*) ctx->GetManagerByGuid(SOUND_MANAGER_GUID);
|
|
if ( wav->GetFileStreaming() && !(wav->m_State & CK_WAVESOUND_STREAMFULLYLOADED) )
|
|
{
|
|
CKSoundReader* reader = wav->GetReader();
|
|
if ( reader )
|
|
{
|
|
// Pause the sound before modifying the reading positions
|
|
if ( Playing )
|
|
sm->Pause(wav, wav->m_Source);
|
|
|
|
// Seek time depends on the reader used
|
|
int SeekTime = 0;
|
|
CKPluginInfo* info = reader->GetReaderInfo();
|
|
if ( info->m_Summary == "DShow Reader" )
|
|
SeekTime = (int) time;
|
|
else if ( info->m_Summary == "Wav Reader" )
|
|
SeekTime = ByteTime; // + 4;
|
|
else {
|
|
#ifdef macintosh
|
|
SeekTime = (int) time;
|
|
#endif
|
|
}
|
|
|
|
// Seek on the reader to decode the requested part
|
|
// Repositiong the playing and reading times
|
|
if ( reader->Seek(SeekTime) != CK_OK ) {
|
|
ctx->OutputToConsoleExBeep("[Sound Seek Error] %s was unable to seek.", info->m_Summary);
|
|
return CKBR_OK;
|
|
}
|
|
wav->m_DataPlayed = ByteTime;
|
|
wav->m_DataRead = ByteTime;
|
|
|
|
// Seek on the sound buffer. We position the reading head one sample before the last
|
|
// readed data to avoid stream overlaping when decoding data below. This sample should
|
|
// not be audible. Also change the oldcursor as we "jump" in the playing process (avoid
|
|
// adding a wrong playing time).
|
|
wav->m_State &= ~CK_WAVESOUND_STREAMOVERLAP;
|
|
sm->SetPlayPosition(wav->m_Source, wav->m_BufferPos - wav->m_WaveFormat.wBitsPerSample/8);
|
|
wav->m_OldCursorPos = sm->GetPlayPosition(wav->m_Source);
|
|
|
|
// We can now decode new datas from the sound file
|
|
if ( wav->WriteDataFromReader() != CK_OK ) {
|
|
ctx->OutputToConsoleExBeep("[Sound Seek Error] Unable to decode sound data.", info->m_Summary);
|
|
return CKBR_OK;
|
|
}
|
|
|
|
// Now, we can start the sound again when it was playing
|
|
if ( Playing )
|
|
sm->Play(wav, wav->m_Source, wav->GetLoopMode());
|
|
}
|
|
}
|
|
else
|
|
sm->SetPlayPosition(wav->m_Source, ByteTime);
|
|
|
|
wav->m_State &= ~CK_WAVESOUND_NEEDREWIND;
|
|
return CKBR_OK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
int
|
|
WaveSeekCallback(const CKBehaviorContext& BehContext)
|
|
{
|
|
CKBehavior* beh = BehContext.Behavior;
|
|
CKContext* ctx = BehContext.Context;
|
|
|
|
//---
|
|
CKBOOL UseProgression;
|
|
beh->GetLocalParameterValue(SET_PROGRESSION, &UseProgression);
|
|
|
|
//---
|
|
CKParameterIn* pin = beh->GetInputParameter(PIN_TIME);
|
|
if ( UseProgression && strcmp(pin->GetName(),"Progression") ) {
|
|
pin->SetName("Progression");
|
|
pin->SetGUID(CKPGUID_PERCENTAGE);
|
|
}
|
|
else if ( !UseProgression && strcmp(pin->GetName(),"Time") ) {
|
|
pin->SetName("Time");
|
|
pin->SetGUID(CKPGUID_TIME);
|
|
}
|
|
|
|
return CKBR_OK;
|
|
}
|