/*********************************************************************** * mt4j Copyright (c) 2008 - 2009, C.Ruff, Fraunhofer-Gesellschaft All rights reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***********************************************************************/ package org.mt4j.components.visibleComponents.widgets.video; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import org.mt4j.components.TransformSpace; import org.mt4j.components.bounds.BoundsZPlaneRectangle; import org.mt4j.components.bounds.IBoundingShape; import org.mt4j.components.visibleComponents.shapes.MTRoundRectangle; import org.mt4j.components.visibleComponents.widgets.MTSlider; import org.mt4j.components.visibleComponents.widgets.buttons.MTSvgButton; import org.mt4j.input.inputProcessors.IGestureEventListener; import org.mt4j.input.inputProcessors.MTGestureEvent; import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragEvent; import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragProcessor; import org.mt4j.input.inputProcessors.componentProcessors.lassoProcessor.IdragClusterable; import org.mt4j.input.inputProcessors.componentProcessors.tapProcessor.TapEvent; import org.mt4j.util.MT4jSettings; import org.mt4j.util.MTColor; import org.mt4j.util.math.Vector3D; import org.mt4j.util.math.Vertex; import org.mt4j.util.opengl.GLConstants; import org.mt4j.util.opengl.GLTexture; import processing.core.PApplet; import processing.core.PImage; import codeanticode.gsvideo.GSMovie; /** * The Class MTMovieClip. * A widget which can be used as a video player. * <br>NOTE: Needs to have the GStreamer framework to be installed on the system. * * @author Christopher Ruff */ public class MTMovieClip extends //MTRectangle MTRoundRectangle implements IdragClusterable { /** The movie. */ private GSMovie movie; /** The first time read. */ private boolean firstTimeRead; /** The selected. */ private boolean selected; /** The play button. */ MTSvgButton playButton; /** * Instantiates a new MT movie clip. * * @param movieFile the movie file * @param upperLeft the upper left * @param pApplet the applet */ public MTMovieClip(String movieFile, Vertex upperLeft, PApplet pApplet) { this(movieFile, upperLeft, 30, pApplet); } /** * Instantiates a new MT movie clip. * * @param movieFile the movie file - located in the ./data directory * @param upperLeft the upper left movie position * @param ifps the ifps the frames per second * @param pApplet the applet */ public MTMovieClip(String movieFile, Vertex upperLeft, int ifps, PApplet pApplet) { // super(upperLeft, 150, 100, pApplet); super(upperLeft.x,upperLeft.y,upperLeft.z, 105,127, 15,15, pApplet); try { movie = new GSMovie(pApplet, movieFile, ifps, this); this.setName("unnamed movieclip"); playButton = new MTSvgButton(MT4jSettings.getInstance().getDefaultSVGPath() + "play.svg" , pApplet); playButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { // movie.play(); switch (arg0.getID()) { case TapEvent.BUTTON_CLICKED: movie.loop(); slider.setVisible(true); break; default: break; } } }); playButton.scale(0.5f, 0.5f, 1, new Vector3D(0,0,0)); playButton.translate(upperLeft); this.addChild(playButton); MTSvgButton stopButton = new MTSvgButton(MT4jSettings.getInstance().getDefaultSVGPath() + "stop.svg" , pApplet); stopButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent arg0) { switch (arg0.getID()) { case TapEvent.BUTTON_CLICKED: movie.stop(); movie.goToBeginning(); slider.setVisible(false); break; default: break; } } }); //TODO m�sste eigentlich gr�sste comp aus svg holen, dann center an die stelle positionieren this.addChild(stopButton); stopButton.scale(0.5f, 0.5f, 1, new Vector3D(0,0,0)); stopButton.translate(new Vector3D(upperLeft.x + 30 , upperLeft.y, upperLeft.z)); } catch (Exception e) { e.printStackTrace(); } firstTimeRead = true; if (MT4jSettings.getInstance().isOpenGlMode()) this.setUseDirectGL(true); try{ PImage movieImg = pApplet.loadImage(MT4jSettings.getInstance().getDefaultImagesPath() + "Crystal_Clear_mimetype_video_cr.png"); this.setTexture(movieImg); this.setTextureEnabled(true); // this.setSizeXYRelativeToParent(movieImg.width, movieImg.height); }catch(Exception e){ e.printStackTrace(); } //Slider this.duration = 0.0f; sliderXOffset = 10; sliderHeight = 10; slider = new MTSlider(upperLeft.x + sliderXOffset, upperLeft.y + this.getHeightXY(TransformSpace.LOCAL) - 30, this.getWidthXY(TransformSpace.LOCAL) - sliderXOffset*2, sliderHeight, 0, 10, pApplet); slider.getOuterShape().setFillColor(new MTColor(0, 0, 0, 80)); slider.getOuterShape().setStrokeColor(new MTColor(0, 0, 0, 80)); slider.getKnob().setFillColor(new MTColor(100, 100, 100, 80)); slider.getOuterShape().setStrokeColor(new MTColor(100, 100, 100, 80)); slider.getKnob().addGestureListener(DragProcessor.class, new IGestureEventListener() { //@Override public boolean processGestureEvent(MTGestureEvent ge) { DragEvent de = (DragEvent)ge; switch (de.getId()) { case MTGestureEvent.GESTURE_DETECTED: dragging = true; break; case MTGestureEvent.GESTURE_UPDATED: break; case MTGestureEvent.GESTURE_ENDED: if (m.isPlaying()){ float currValue = slider.getValue(); jump(currValue); } dragging = false; break; default: break; } return false; } }); this.addChild(slider); slider.setVisible(false); dragging = false; } /* (non-Javadoc) * @see org.mt4j.components.visibleComponents.shapes.MTRoundRectangle#computeDefaultBounds() */ @Override protected IBoundingShape computeDefaultBounds() { return new BoundsZPlaneRectangle(this); } /** The slider. */ private MTSlider slider; /** The dragging. */ private boolean dragging; /** The slider x offset. */ private int sliderXOffset; /** The slider height. */ private int sliderHeight; /** The m. */ private GSMovie m; /** * Movie event. * * @param myMovie the my movie * * @throws InterruptedException the interrupted exception */ public void movieEvent(GSMovie myMovie) throws InterruptedException { m = myMovie; if (!dragging){ slider.setValue(myMovie.time()); //ONLY DO THIS WHEN NOT DRAGGING THE SLIDER } if (firstTimeRead && myMovie.available() ){ myMovie.read(); System.out.println("Movie img format: " + m.format); //FIXME TEST - dont do every frame! Duration is only valid if playing.. slider.setValueRange(0, myMovie.duration()); this.setSizeLocal(m.width, m.height); // /* slider.setSizeXYRelativeToParent(m.width - 2*sliderXOffset, sliderHeight); Vector3D movieClipCenterLocal = this.getCenterPointLocal(); slider.setPositionRelativeToParent(new Vector3D(movieClipCenterLocal.x, movieClipCenterLocal.y + this.getHeightXY(TransformSpace.LOCAL)*0.5f - slider.getHeightXY(TransformSpace.RELATIVE_TO_PARENT)*0.5f - 5,0 )); // */ // this.setUseDirectGL(false); this.setTexture(null); //TO force to rescale of new texture coordianates to RECTANGLE (0..width) this.setTexture(m); this.setTextureEnabled(true); // this.setUseDirectGL(true); firstTimeRead = false; } } /* (non-Javadoc) * @see com.jMT.components.MTBaseComponent#updateComponent(long) */ @Override public void updateComponent(long timeDelta){ super.updateComponent(timeDelta); // /* if ( m != null && m.isPlaying() && m.available() //if unread frame available ){ if (this.getTexture() instanceof GLTexture){ if (this.isUseDirectGL() && MT4jSettings.getInstance().isOpenGlMode()){ //Directly put the new frame buffer into the texture only if in openGL mode //without filling the PImage array of this objects texture and also not of the GSMovie PImage =>performance ((GLTexture)this.getTexture()).putBuffer(m.getMoviePixelsBuffer(), GLConstants.TEX4, GLConstants.TEX_UBYTE); }else{ //Fill the PImage with the new movieframe //dont fill the openGL texture m.read(); ((GLTexture)this.getTexture()).putImageOnly(m); } }else{ //Usually all textures should be GLTextures instances, but just to be sure.. m.read(); this.setTexture(m); //SLOW! } } // */ } //FIXME TEST /** The duration. */ float duration; /** * Gets the duration. * * @return the duration */ public float getDuration(){//duration only valid if video is playing if (movie.duration() == 0.0){ return duration; }else{ duration = movie.duration(); return duration; } } /** * Jump. * * @param where the where */ public void jump(float where) { movie.jump(where); } /** * Loop the movie. */ public void loop() { movie.loop(); } /** * No looping. */ public void noLoop() { movie.noLoop(); } /** * Pause. */ public void pause() { movie.pause(); } /** * Play. */ public void play() { movie.play(); } /** * Stop. */ public void stop() { movie.stop(); } /** * Time. * * @return the time the movie plays in float */ public float getTime() { return movie.time(); } /* (non-Javadoc) * @see com.jMT.input.inputAnalyzers.clusterInputAnalyzer.IdragClusterable#isSelected() */ public boolean isSelected() { return selected; } /* (non-Javadoc) * @see com.jMT.input.inputAnalyzers.clusterInputAnalyzer.IdragClusterable#setSelected(boolean) */ public void setSelected(boolean selected) { this.selected = selected; } }