deargui-vpl/ref/virtools/Samples/Behaviors/Sound/behaviors src/WaveSeek.cpp

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;
}