/* * Created on Jul 2, 2007 Copyright (C) 2001-2007, Anthony Harrison * anh23@pitt.edu (jactr.org) This library is free software; you can * redistribute it and/or modify it under the terms of the GNU Lesser General * Public License as published by the Free Software Foundation; either version * 2.1 of the License, or (at your option) any later version. This library is * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.jactr.modules.pm.aural.buffer.six; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jactr.core.buffer.delegate.ExpandChunkRequestDelegate; import org.jactr.core.chunk.IChunk; import org.jactr.core.chunk.ISymbolicChunk; import org.jactr.core.chunktype.IChunkType; import org.jactr.core.logging.Logger; import org.jactr.core.model.IModel; import org.jactr.core.production.request.ChunkTypeRequest; import org.jactr.core.queue.ITimedEvent; import org.jactr.core.slot.BasicSlot; import org.jactr.core.slot.IMutableSlot; import org.jactr.modules.pm.aural.IAuralModule; import org.jactr.modules.pm.aural.buffer.IAuralLocationBuffer; import org.jactr.modules.pm.aural.buffer.processor.AuralSearchRequestDelegate; import org.jactr.modules.pm.buffer.IPerceptualBuffer; import org.jactr.modules.pm.common.buffer.AbstractPMActivationBuffer6; /** * Supports clearing unique fields of the audio-event permiting merging. * * @author developer */ public class DefaultAuralLocationBuffer extends AbstractPMActivationBuffer6 implements IAuralLocationBuffer { /** * logger definition */ static private final Log LOGGER = LogFactory .getLog(DefaultAuralLocationBuffer.class); protected ITimedEvent _pendingScan; protected boolean _stuffPending; protected boolean _nullUniqueSlots = true; /** * @param name * @param model * @param module */ public DefaultAuralLocationBuffer(IAuralModule module) { super(IAuralModule.AURAL_LOCATION_BUFFER, module); } public void setCompressAudioEventsEnabled(boolean compressAudioEvents) { _nullUniqueSlots = compressAudioEvents; } public boolean isCompressAudioEventsEnabled() { return _nullUniqueSlots; } @Override public void enqueueTimedEvent(ITimedEvent timedEvent) { _pendingScan = timedEvent; super.enqueueTimedEvent(timedEvent); } @Override public void initialize() { super.initialize(); } @Override protected void grabReferences() { /* * this will expand any inserted chunk requests to chunktype requests. this * allows the modeler to do a +visual-location> =oldLoc which will then * start a new search */ addRequestDelegate(new ExpandChunkRequestDelegate(false)); addRequestDelegate(new AuralSearchRequestDelegate( (IAuralModule) getModule())); super.grabReferences(); } @Override protected void setSourceChunkInternal(IChunk chunk) { super.setSourceChunkInternal(chunk); IModel model = getModel(); if (Logger.hasLoggers(model)) Logger.log(model, Logger.Stream.AURAL, getName() + " current audio event " + chunk); } /** * @see org.jactr.modules.pm.common.buffer.AbstractPMActivationBuffer6#isValidChunkType(org.jactr.core.chunktype.IChunkType) */ @Override protected boolean isValidChunkType(IChunkType chunkType) { return chunkType != null && chunkType.isA(((IAuralModule) getModule()).getAudioEventChunkType()); } public void checkForBufferStuff() { IAuralModule aModule = (IAuralModule) getModule(); /* * can't stuff if full, requested, unrequested */ if (!isBufferEmpty()) { if (LOGGER.isDebugEnabled()) LOGGER.debug(getName() + ".buffer is not empty(" + getSlot("buffer").getValue() + "), can't stuff"); return; } /* * or busy */ if (isStateBusy()) { if (LOGGER.isDebugEnabled()) LOGGER.debug(getName() + ".state is busy, can't stuff"); return; } if (LOGGER.isDebugEnabled()) LOGGER.debug("Setting search pattern for buffer stuff"); /* * there is some stuffing to do.. lets do a basic search for anything new, * near the center of view note: this is not the same as lisp which looks * for the newest left most (WTF?). */ ChunkTypeRequest locationBufferStuffPattern = new ChunkTypeRequest( aModule.getAudioEventChunkType()); locationBufferStuffPattern.addSlot(new BasicSlot( IAuralModule.ATTENDED_STATUS_SLOT, getModel().getDeclarativeModule() .getNewChunk())); locationBufferStuffPattern.addSlot(new BasicSlot( IPerceptualBuffer.IS_BUFFER_STUFF_REQUEST, true)); IModel model = getModel(); if (Logger.hasLoggers(model)) Logger.log(model, Logger.Stream.AURAL, "Attempting a stuff search with " + locationBufferStuffPattern); _stuffPending = true; request(locationBufferStuffPattern, getModel().getAge()); } public boolean isBufferStuffPending() { return _pendingScan != null && _stuffPending; } public void cancelBufferStuff() { if (isBufferStuffPending()) { _pendingScan.abort(); _pendingScan = null; _stuffPending = false; } } /** * overriden so that we can null out the time values for better merge * behavior. */ @Override protected boolean removeSourceChunkInternal(IChunk chunkToRemove) { super.removeSourceChunkInternal(chunkToRemove); if (isCompressAudioEventsEnabled()) { try { ISymbolicChunk sc = chunkToRemove.getSymbolicChunk(); ((IMutableSlot) sc.getSlot(IAuralModule.ONSET_SLOT)).setValue(null); ((IMutableSlot) sc.getSlot(IAuralModule.OFFSET_SLOT)).setValue(null); } catch (Exception e) { LOGGER.debug( "Failed to clear audio-event contents. Leaving untouched. ", e); } return true; } return false; } }