All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.robokind.api.animation.messaging.RemoteAnimationPlayerClient Maven / Gradle / Ivy

/*
 * Copyright 2012 Hanson Robokind LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.robokind.api.animation.messaging;

import java.util.ArrayList;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jflux.api.core.Listener;
import org.jflux.api.core.util.DefaultNotifier;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.robokind.api.animation.Animation;
import org.robokind.api.animation.Channel;
import org.robokind.api.animation.MotionPath;
import org.robokind.api.animation.player.AnimationJob;
import org.robokind.api.animation.player.AnimationPlayer;
import org.robokind.api.animation.protocol.AnimationEvent;
import org.robokind.api.animation.protocol.AnimationEvent.AnimationEventFactory;
import org.robokind.api.animation.protocol.AnimationSignal;
import org.robokind.api.common.config.VersionProperty;
import org.robokind.api.common.playable.Playable;
import org.robokind.api.common.services.addon.ServiceAddOn;
import org.robokind.api.common.utils.TimeUtils;
import org.robokind.api.messaging.MessageAsyncReceiver;
import org.robokind.api.messaging.MessageSender;

/**
 *
 * @author Matthew Stevenson 
 */
public class RemoteAnimationPlayerClient
    extends DefaultNotifier
    implements AnimationPlayer, Listener{
    private final static Logger theLogger =
            Logger.getLogger(RemoteAnimationPlayerClient.class.getName());
    private String myAnimationPlayerId;
    private String myRemotePlayerId;
    private MessageSender myAnimationSender;
    private AnimationEventFactory myEventFactory;
    private List myAnimationJobs;
    private MessageAsyncReceiver mySignalReceiver;
    private BundleContext myContext;
    private Map myRegistry;

    public RemoteAnimationPlayerClient(
            BundleContext context, String animPlayerClientId,
            String animPlayerHostId){
        if(animPlayerClientId == null || animPlayerHostId == null){
            throw new NullPointerException();
        }
        myAnimationPlayerId = animPlayerClientId;
        myRemotePlayerId = animPlayerHostId;
        myContext = context;
        myRegistry = new HashMap();
        myAnimationJobs = new ArrayList();
    }
    
    @Override
    public String getAnimationPlayerId(){
        return myAnimationPlayerId;
    }
    
    public void setAnimationEventFactory(AnimationEventFactory factory){
        myEventFactory = factory;
    }
    
    public void setAnimationEventSender(MessageSender sender){
        myAnimationSender = sender;
    }
    
    public void setAnimationSignalReceiver(
            MessageAsyncReceiver receiver){
        if(mySignalReceiver != null){
            mySignalReceiver.removeListener(this);
        }
        
        mySignalReceiver = receiver;
        
        if(mySignalReceiver != null){
            mySignalReceiver.addListener(this);
        }
    }
    
    public AnimationJob playAnimation(Animation animation, boolean register) {
        if(myEventFactory == null || myAnimationSender == null){
            return null;
        }
        String[] names = new String[]{
            AnimationJob.class.getName(),
        };
        AnimationEvent event = 
                myEventFactory.createAnimationEvent(
                        myAnimationPlayerId, myRemotePlayerId, animation);
        myAnimationSender.notifyListeners(event);
        for(ServiceAddOn add : animation.getAddOns()){
            add.getAddOn().start(TimeUtils.now());
        }
        RemoteAnimationJob job = new RemoteAnimationJob(this, animation,
                animation.getStartTime(), animation.getStopTime(),  800);
        if(register && myContext != null){
            Dictionary props = new Properties();
            ServiceRegistration reg =
                    myContext.registerService(names, job, props);
            myRegistry.put(job, reg);
        }
        myAnimationJobs.add(job);
        job.start(TimeUtils.now());
        return job;
    }
    
    @Override
    public AnimationJob playAnimation(Animation animation) {
        return playAnimation(animation, true);
    }
    
    public AnimationJob loopAnimation(Animation animation, boolean register) {
        if(myEventFactory == null || myAnimationSender == null){
            return null;
        }
        String[] names = new String[]{
            AnimationJob.class.getName(),
        };
        AnimationEvent event = 
                myEventFactory.createAnimationEvent(
                        myAnimationPlayerId, "LOOP", animation);
        myAnimationSender.notifyListeners(event);
        for(ServiceAddOn add : animation.getAddOns()){
            add.getAddOn().start(TimeUtils.now());
        }
        AnimationJob job = new RemoteAnimationJob(this, animation, 
                animation.getStartTime(), animation.getStopTime(),  800);
        if(register && myContext != null){
            Dictionary props = new Properties();
            ServiceRegistration reg =
                    myContext.registerService(names, job, props);
            myRegistry.put(job, reg);
        }
        job.start(TimeUtils.now());
        return job;
    }
    
    public AnimationJob loopAnimation(Animation animation) {
        return loopAnimation(animation, true);
    }
    
    public void stopAnimation(Animation animation) {
        if(myEventFactory == null || myAnimationSender == null){
            return;
        }
        AnimationEvent event = 
                myEventFactory.createAnimationEvent(
                        myAnimationPlayerId, "STOP", animation);
        myAnimationSender.notifyListeners(event);
        for(ServiceAddOn add : animation.getAddOns()){
            add.getAddOn().stop(TimeUtils.now());
        }
    }
    
    public void clearAnimations() {
        if(myEventFactory == null || myAnimationSender == null){
            return;
        }
        Animation empty = new Animation(new VersionProperty("empty", "1.0"));
        empty.addChannel(new Channel(0, "emptyChan"));
        MotionPath path = new MotionPath();
        path.addPoint(0, 0.5);
        path.addPoint(1, 0.5);
        empty.getChannel(0).addPath(path);
        AnimationEvent event = 
                myEventFactory.createAnimationEvent(
                        myAnimationPlayerId, "CLEAR", empty);
        myAnimationSender.notifyListeners(event);
        return;
    }

    @Override
    public AnimationJob playAnimation(Animation animation, Long start, Long stop) {
        animation.setStartTime(start);
        animation.setStopTime(stop);
        return playAnimation(animation);
    }

    @Override
    public List getCurrentAnimations() {
        return (List)myAnimationJobs;
    }

    @Override
    public void removeAnimationJob(AnimationJob job) {
        if(!(job instanceof RemoteAnimationJob)){
            return;
        }
        RemoteAnimationJob rjob = (RemoteAnimationJob)job;
        if(!myAnimationJobs.contains(rjob)){
            return;
        }
        rjob.stop(TimeUtils.now());
        if(myContext != null) {
            ServiceRegistration reg = myRegistry.remove(job);
            if(reg == null){
                return;
            }
            try{
                reg.unregister();
            }catch(IllegalStateException ex){
                theLogger.log(
                        Level.WARNING,
                        "Unable to unregister AnimationJob.  Already unregistered.",
                        ex);
            }
        }
        myAnimationJobs.remove(rjob);
    }

    @Override
    public void addAnimationSignalListener(Listener listener) {
        myListeners.add(listener);
    }

    @Override
    public void removeAnimationSignalListener(
            Listener listener) {
        myListeners.remove(listener);
    }    

    @Override
    public void handleEvent(AnimationSignal t) {
        boolean hashFound = false;
        RemoteAnimationJob goodJob = null;
        
        for(RemoteAnimationJob job: myAnimationJobs) {
            if(job.getAnimation().hashCode() == t.getAnimationHash()) {
                hashFound = true;
                goodJob = job;
                break;
            }
        }
        
        if(!hashFound) {
            for(RemoteAnimationJob job: myAnimationJobs) {
                if(job.getAnimation().getVersion().getName().equals(
                        t.getAnimationName()) &&
                        job.getAnimation().getVersion().getNumber().equals(
                        t.getAnimationVersion())) {
                    goodJob = job;
                    break;
                }
            }
        }
        
        if(goodJob != null) {
            if(t.getEventType().equals(AnimationSignal.EVENT_START)) {
                goodJob.start(TimeUtils.now());
            } else if(t.getEventType().equals(AnimationSignal.EVENT_PAUSE)) {
                goodJob.pause(TimeUtils.now());
            } else if(t.getEventType().equals(AnimationSignal.EVENT_RESUME)) {
                goodJob.resume(TimeUtils.now());
            } else if(t.getEventType().equals(AnimationSignal.EVENT_CANCEL)) {
                goodJob.stop(TimeUtils.now());
            } else if(t.getEventType().equals(AnimationSignal.EVENT_COMPLETE)) {
                goodJob.complete(TimeUtils.now());
            }
        }
        
        notifyListeners(t);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy