Skip to content
This repository has been archived by the owner on Oct 9, 2018. It is now read-only.

Commit

Permalink
More reworking of dynamic stimuli
Browse files Browse the repository at this point in the history
* Eliminated the previously-added "finalize" pass for actions.  Stimulus group references that depend on global variables cannot be fully resolved at parse time, so the dynamic stimulus actions *must* validate their target at execution time.
* Dynamic stimuli once again do not play by default.  Instead, StandardDynamicStimulus now supports an "autoplay" parameter.  A non-playing SDS subclass with autoplay set to true will automatically start playing the first time it draws (i.e. during the first stimulus display update after it's queued).
* Subclasses of DynamicStimulusDriver that need to perform additional actions when they start or stop should now override startPlaying() or stopPlaying(), respectively (being sure to call the base implementation from the override)
* Subclasses of StandardDynamicStimulus should once again implement drawFrame().  However, the function now takes only one argument (the StimulusDisplay pointer).
* Added some code to ensure that StimulusDisplay::getCurrentOutputTimeUS() always returns a valid time when the state system is running
  • Loading branch information
cstawarz committed Aug 23, 2011
1 parent 5b26cc5 commit 2d9c7ab
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 46 deletions.
25 changes: 14 additions & 11 deletions Core/Stimuli/DynamicStimuli/DynamicStimulusActions.cpp
Expand Up @@ -29,17 +29,6 @@ DynamicStimulusAction::DynamicStimulusAction(const ParameterValueMap &parameters
{ }


void DynamicStimulusAction::finalize(std::map<std::string, std::string> parameters, ComponentRegistryPtr reg) {
Action::finalize(parameters, reg);

stimulus = boost::dynamic_pointer_cast<DynamicStimulusDriver>(stimulusNode->getStimulus());

if (!stimulus) {
throw SimpleException("Action target is not a dynamic stimulus", stimulusNode->getStimulus()->getTag());
}
}


void PlayDynamicStimulus::describeComponent(ComponentInfo &info) {
DynamicStimulusAction::describeComponent(info);
info.setSignature("action/play_dynamic_stimulus");
Expand All @@ -54,6 +43,13 @@ PlayDynamicStimulus::PlayDynamicStimulus(const ParameterValueMap &parameters) :


bool PlayDynamicStimulus::execute() {
DynamicStimulusDriverPtr stimulus(getDynamicStimulus());

if (!stimulus) {
merror(M_PARADIGM_MESSAGE_DOMAIN, "Attempted to play a non-dynamic stimulus. Doing nothing.");
return false;
}

stimulus->play();
return true;
}
Expand All @@ -73,6 +69,13 @@ StopDynamicStimulus::StopDynamicStimulus(const ParameterValueMap &parameters) :


bool StopDynamicStimulus::execute() {
DynamicStimulusDriverPtr stimulus(getDynamicStimulus());

if (!stimulus) {
merror(M_PARADIGM_MESSAGE_DOMAIN, "Attempted to stop a non-dynamic stimulus. Doing nothing.");
return false;
}

stimulus->stop();
return true;
}
Expand Down
7 changes: 4 additions & 3 deletions Core/Stimuli/DynamicStimuli/DynamicStimulusActions.h
Expand Up @@ -28,11 +28,12 @@ class DynamicStimulusAction : public Action {

virtual ~DynamicStimulusAction() { }

virtual void finalize(std::map<std::string, std::string> parameters, ComponentRegistryPtr reg);

protected:
DynamicStimulusDriverPtr getDynamicStimulus() {
return boost::dynamic_pointer_cast<DynamicStimulusDriver>(stimulusNode->getStimulus());
}

StimulusNodePtr stimulusNode;
DynamicStimulusDriverPtr stimulus;

};

Expand Down
38 changes: 23 additions & 15 deletions Core/Stimuli/DynamicStimuli/DynamicStimulusDriver.cpp
Expand Up @@ -10,7 +10,6 @@
#include "DynamicStimulusDriver.h"

#include "StandardVariables.h"
#include "StimulusDisplay.h"

#include <boost/bind.hpp>

Expand All @@ -19,7 +18,6 @@ BEGIN_NAMESPACE_MW


DynamicStimulusDriver::DynamicStimulusDriver() :
playing(true),
startTime(NOT_STARTED)
{
stateSystemCallbackNotification =
Expand All @@ -35,35 +33,45 @@ DynamicStimulusDriver::~DynamicStimulusDriver() {

void DynamicStimulusDriver::stateSystemCallback(const Datum &data, MWorksTime time) {
if (data.getInteger() == IDLE) {
boost::mutex::scoped_lock locker(stim_lock);
playing = true;
startTime = NOT_STARTED;
stop();
}
}


void DynamicStimulusDriver::play() {
boost::mutex::scoped_lock locker(stim_lock);
playing = true;

if (!isPlaying()) {
startPlaying();
}
}


void DynamicStimulusDriver::stop() {
boost::mutex::scoped_lock locker(stim_lock);
playing = false;
startTime = NOT_STARTED;

if (isPlaying()) {
stopPlaying();
}
}


MWTime DynamicStimulusDriver::getElapsedTime() {
MWTime currentFrameTime = StimulusDisplay::getCurrentStimulusDisplay()->getCurrentOutputTimeUS();

if (NOT_STARTED == startTime) {
startTime = currentFrameTime;
return 0LL;
MWTime DynamicStimulusDriver::getElapsedTime() const {
if (!isPlaying()) {
return NOT_STARTED;
}

return currentFrameTime - startTime;
return getCurrentTime() - startTime;
}


void DynamicStimulusDriver::startPlaying() {
startTime = getCurrentTime();
}


void DynamicStimulusDriver::stopPlaying() {
startTime = NOT_STARTED;
}


Expand Down
12 changes: 7 additions & 5 deletions Core/Stimuli/DynamicStimuli/DynamicStimulusDriver.h
Expand Up @@ -10,7 +10,7 @@
#ifndef DYNAMIC_STIMULUS_H
#define DYNAMIC_STIMULUS_H

#include "StandardStimuli.h"
#include "StimulusDisplay.h"
#include "VariableNotification.h"

#include <boost/noncopyable.hpp>
Expand All @@ -34,16 +34,18 @@ class DynamicStimulusDriver : boost::noncopyable {
protected:
static const MWTime NOT_STARTED = -1LL;

bool isPlaying() const { return playing; }
bool isPlaying() const { return (startTime != NOT_STARTED); }
MWTime getStartTime() const { return startTime; }
MWTime getElapsedTime();
MWTime getCurrentTime() const { return StimulusDisplay::getCurrentStimulusDisplay()->getCurrentOutputTimeUS(); }
MWTime getElapsedTime() const;

virtual void startPlaying();
virtual void stopPlaying();

boost::mutex stim_lock;

private:
bool playing;
MWTime startTime;

boost::shared_ptr<VariableCallbackNotification> stateSystemCallbackNotification;

};
Expand Down
22 changes: 21 additions & 1 deletion Core/Stimuli/DynamicStimuli/StandardDynamicStimulus.cpp
Expand Up @@ -12,13 +12,18 @@
BEGIN_NAMESPACE_MW


const std::string StandardDynamicStimulus::AUTOPLAY("autoplay");


void StandardDynamicStimulus::describeComponent(ComponentInfo &info) {
Stimulus::describeComponent(info);
info.addParameter(AUTOPLAY, "0");
}


StandardDynamicStimulus::StandardDynamicStimulus(const ParameterValueMap &parameters) :
Stimulus(parameters)
Stimulus(parameters),
autoplay(parameters[AUTOPLAY])
{
}

Expand All @@ -28,6 +33,21 @@ bool StandardDynamicStimulus::needDraw() {
}


void StandardDynamicStimulus::draw(shared_ptr<StimulusDisplay> display) {
boost::mutex::scoped_lock locker(stim_lock);

if (!isPlaying()) {
if (autoplay->getValue().getBool()) {
startPlaying();
} else {
return;
}
}

drawFrame(display);
}


Datum StandardDynamicStimulus::getCurrentAnnounceDrawData() {
Datum announceData(M_DICTIONARY, 5);
announceData.addElement(STIM_NAME, tag);
Expand Down
10 changes: 9 additions & 1 deletion Core/Stimuli/DynamicStimuli/StandardDynamicStimulus.h
Expand Up @@ -9,8 +9,8 @@
#ifndef StandardDynamicStimulus_H_
#define StandardDynamicStimulus_H_

#include "DynamicStimulusDriver.h"
#include "Stimulus.h"
#include "DynamicStimulusDriver.h"
#include "ComponentInfo.h"
#include "ParameterValue.h"

Expand All @@ -21,15 +21,23 @@ BEGIN_NAMESPACE_MW
class StandardDynamicStimulus : public Stimulus, public DynamicStimulusDriver {

public:
static const std::string AUTOPLAY;

static void describeComponent(ComponentInfo &info);

explicit StandardDynamicStimulus(const ParameterValueMap &parameters);

virtual ~StandardDynamicStimulus() { }

virtual bool needDraw();
virtual void draw(shared_ptr<StimulusDisplay> display);
virtual void drawFrame(shared_ptr<StimulusDisplay> display) = 0;

virtual Datum getCurrentAnnounceDrawData();

protected:
VariablePtr autoplay;

};


Expand Down
7 changes: 5 additions & 2 deletions Core/Stimuli/StimulusDisplay.cpp
Expand Up @@ -196,6 +196,9 @@ void StimulusDisplay::stateSystemCallback(const Datum &data, MWorksTime time) {
{
merror(M_DISPLAY_MESSAGE_DOMAIN, "Unable to start display updates");
} else {
// Wait for a refresh to complete, so we know that getCurrentOutputTimeUS() will return a valid time
ensureRefresh(lock);

mprintf(M_DISPLAY_MESSAGE_DOMAIN,
"Display updates started (main = %d, current = %d)",
CGMainDisplayID(),
Expand Down Expand Up @@ -340,6 +343,7 @@ void StimulusDisplay::clearDisplay() {
}
}

needDraw = true;
ensureRefresh(upgradeLock);
}

Expand Down Expand Up @@ -423,6 +427,7 @@ void StimulusDisplay::updateDisplay() {
MWTime before_draw = clock->getCurrentTimeUS();
#endif

needDraw = true;
ensureRefresh(upgradeLock);

#ifdef ERROR_ON_LATE_FRAMES
Expand All @@ -441,8 +446,6 @@ void StimulusDisplay::updateDisplay() {

void StimulusDisplay::ensureRefresh(upgrade_lock &lock) {
shared_lock sharedLock(lock); // Downgrade to shared_lock

needDraw = true;

if (!CVDisplayLinkIsRunning(displayLink)) {
// Need to do the refresh here
Expand Down
8 changes: 0 additions & 8 deletions Core/XMLParser/MWParserTransformation.xsl
Expand Up @@ -34,7 +34,6 @@
<xsl:apply-templates mode="action_create"/>
<xsl:apply-templates mode="action_connect"/>
<xsl:apply-templates mode="spring_loaded_action_connect"/>
<xsl:apply-templates mode="action_finalize"/>

<xsl:apply-templates mode="list_connect"/>

Expand Down Expand Up @@ -677,13 +676,6 @@
</xsl:template>
<xsl:template match="text()" mode = "iodevice_finalize"/>

<!-- Actions -->
<xsl:template match="//action" mode="action_finalize">
<xsl:call-template name="generic_finalize"/>
<xsl:apply-templates select="node()" mode="action_finalize"/>
</xsl:template>
<xsl:template match="text()" mode = "action_finalize"/>

<!-- ********************* -->
<!-- Variable assignments -->
<!-- ********************* -->
Expand Down

0 comments on commit 2d9c7ab

Please sign in to comment.