/***********************************************************************
* 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 org.mt4j.components.bounds.BoundsZPlaneRectangle;
import org.mt4j.components.bounds.IBoundingShape;
import org.mt4j.components.visibleComponents.shapes.MTRectangle;
import org.mt4j.util.MT4jSettings;
import org.mt4j.util.math.Vertex;
import org.mt4j.util.opengl.GLTexture;
import processing.core.PApplet;
import codeanticode.gsvideo.GSMovie;
/**
* This class allows to run a video texture on a plain MTRectangle without any
* UI-Controls.
* <br>NOTE: Needs to have the GStreamer framework to be installed on the system.
*
* @author Christopher Ruff
*/
public class MTVideoTexture extends
MTRectangle
//MTRoundRectangle
{
/** The movie. */
protected GSMovie movie;
/** The m. */
private GSMovie m;
/** The first time read. */
private boolean firstTimeRead;
/** The duration. */
float duration;
/**
* Instantiates a MTVideoTexture
*
* @param movieFile the movie file
* @param upperLeft the upper left
* @param pApplet the applet
*/
public MTVideoTexture(String movieFile, Vertex upperLeft, PApplet pApplet) {
this(movieFile, upperLeft, 30, pApplet);
}
/**
* Instantiates a new MTVideoTexture
*
* @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 MTVideoTexture(String movieFile, Vertex upperLeft, int ifps, PApplet pApplet) {
// super(upperLeft, 150, 100, pApplet);
super(upperLeft.x,upperLeft.y,upperLeft.z, 105,127, pApplet);
this.duration = 0.0f;
this.setName("movieclip: " + movieFile);
firstTimeRead = true;
try {
movie = new GSMovie(pApplet, movieFile, ifps);
movie.setEventHandlerObject(this);
// if (pApplet instanceof MTApplication) {
// MTApplication app = (MTApplication) pApplet;
// movie.play();
// app.invokeLater(new Runnable() {
// public void run() {
// movie.pause();
// }
// });
// }
if (MT4jSettings.getInstance().isOpenGlMode()){
this.setUseDirectGL(true);
}
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected IBoundingShape computeDefaultBounds() {
return new BoundsZPlaneRectangle(this);
}
/**
* 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
// }
}
public GSMovie getMovie(){
return this.movie;
}
protected void onFirstFrame(){
if (m.available()){
m.read();
System.out.println("Movie img format: " + m.format);
this.setSizeLocal(m.width, m.height);
// this.setTexture(null); //TO force to rescale of new texture coordianates to RECTANGLE (0..width)
this.setTexture(m); //FIXME this will call glGenTextures from NOT OPENGL THREAD! FIX THIS!
this.setTextureEnabled(true);
//FIXME try to use PBO for pixel->texture transfer -> even slower??
if (this.getTexture() instanceof GLTexture){
// GLTexture glTex = (GLTexture)this.getTexture();
// glTex.enableFastTextureLoad();
}
}
}
protected void onNewFrame(){
}
@Override
public void updateComponent(long timeDelta){
super.updateComponent(timeDelta);
if (m != null){
if (firstTimeRead && m.available()){
this.onFirstFrame();
firstTimeRead = false;
}
else{
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
// ((MTTexture)this.getTexture()).putBuffer(m.getMoviePixelsBuffer(), GLConstants.TEX4, GLConstants.TEX_UBYTE);
((GLTexture)this.getTexture()).updateGLTexture(m.getMoviePixelsBuffer());
}else{
//Fill the PImage with the new movieframe
//dont fill the openGL texture
m.read();
// ((MTTexture)this.getTexture()).putImageOnly(m);
((GLTexture)this.getTexture()).loadPImageTexture(m);
}
}else{
//Usually all textures should be GLTextures instances, but just to be sure..
m.read();
this.setTexture(m); //SLOW!!!
}
this.onNewFrame();
}
}
}
}
@Override
protected void destroyComponent() {
super.destroyComponent();
if (m != null){
m.dispose();
}
}
/**
* Gets the duration.
*
* @return the duration
*/
public float getDuration(){//duration only valid if video is playing
GSMovie movie = getMovie();
if (movie.duration() == 0.0){
return duration;
}else{
duration = movie.duration();
return duration;
}
}
/**
* Jump.
*
* @param where the where
*/
public void jump(float where) {
GSMovie movie = getMovie();
movie.jump(where);
}
/**
* Play.
*/
public void play() {
GSMovie movie = getMovie();
movie.play();
}
/**
* Stop.
*/
public void stop() {
GSMovie movie = getMovie();
movie.stop();
}
/**
* Loop the movie.
*/
public void loop() {
GSMovie movie = getMovie();
movie.loop();
}
/**
* No looping.
*/
public void noLoop() {
GSMovie movie = getMovie();
movie.noLoop();
}
/**
* Pause.
*/
public void pause() {
GSMovie movie = getMovie();
movie.pause();
}
/**
* Time.
*
* @return the time the movie plays in float
*/
public float getTime() {
GSMovie movie = getMovie();
return movie.time();
}
/**
* Go to beginning.
*/
public void goToBeginning() {
GSMovie movie = getMovie();
movie.goToBeginning();
}
/**
* Change the volume. Values are from 0 to 1.
* @param v the new volume
*/
public void setVolume(double v){
getMovie().volume(v);
}
}