Simple program for randomly displaying videos

Hello everyone,

First of all, I’m really new to OF, and C++ ! (and pardon my english mistakes, not my first language !)
I’ve coded simple things before in Javascript and Processing, and I’m trying to learn C++ and OF now.

The reason I use C++ is I need to display HD video, and the others languages aren’t fast enough – and also that I’m simply curious to have more knowledge of programming :slight_smile:

My code should display a continuous video made of about 20 different shots, with a random order determined in real time. Meaning at the end of each shot, the next shot is picked randomly in the video files.
(it should look like this : http://vimeo.com/102019579 – this is “faked” random in a cut video file of course)

I have made a simple example with only 3 videos, for starters, and managed to make it work. (I started with the videoplayer example of OF)

Now I wanted to add in a new rule, so that to identical shots could not follow each other. So, I need to have two random values, to compare the new generated to the old one, and regenerate if identical.
So this means, if I understood well, that I need to use pointers in order to keep track of the old value in two separate executions of the same function. Right ?

I tried that, but the compiler is giving me an error saying the pointer wasn’t declared even though I declared it in setup :
line 8 " ‘randNum’ was not declared in this scope "
There must be something I’m doing wrong with the pointers, because I’m new to this concept, but I can’t see what, and after a few hours of searching, I’m still stuck with no idea … so … any help would be very welcome :smiley:

Here is my code in ofApp.cpp :

#include "math.h"
#include "ofApp.h"

void ofApp::loadAndPlay () {

    //cout << " pointer in loadAndPlay function: " << randNum ; //adresse

    *randNum = floor(ofRandom(3));
    cout << *randNum;

    switch(*randNum) {
        case 0:
            bikeMovie.loadMovie("movies/14.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 1:
            bikeMovie.loadMovie("movies/16.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        default:
            bikeMovie.loadMovie("movies/9.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
    }


}
//--------------------------------------------------------------
void ofApp::setup(){
    ofBackground(0,0,0);

    unsigned int randomNumber(5);
    //cout << "value : " << randomNumber ;

    unsigned int *randNum(0);
    //cout << " , empty pointer: " << randNum ;

    randNum = &randomNumber ;
    //cout << " , pointer : " << randNum ;
    //cout << " , pointer value : " << *randNum ;

    loadAndPlay();
}

//--------------------------------------------------------------
void ofApp::update(){
    bikeMovie.update();
}

//--------------------------------------------------------------
void ofApp::draw(){
    bikeMovie.draw(0,0);

    if(bikeMovie.getIsMovieDone()){
            loadAndPlay();
    }
}

I don’t know whether it’s helpfull or not, but there are my ofApp.h and main.cpp :

#ifndef MATH_H_INCLUDED
#define MATH_H_INCLUDED

#pragma once

#include "ofMain.h"

class ofApp : public ofBaseApp{

    public:

        void setup();
        void update();
        void draw();
        void loadAndPlay();

        ofVideoPlayer bikeMovie;

};

#endif // MATH_H_INCLUDED

#include "ofMain.h"
#include "ofApp.h"

//========================================================================
int main( ){

    ofSetupOpenGL(1024,768, OF_FULLSCREEN);            // <-------- setup the GL context

    // this kicks off the running of my app
    // can be OF_WINDOW or OF_FULLSCREEN
    // pass in width and height too:
    ofRunApp( new ofApp());

}

Next I wanted to ask you about optimization, in order to display fluently HD 1080p videos, but first things first, as I can’t manage to make this work.
(about that, I was wondering if it’s best to have several files and play them next to each other, or to have the playhead moving randomly on indexed positions of one big file – in which case I would have to review my program almost from start !)

Thanks a lot for your help

Pablo

1 Like

Hey @pablo_paris

A method I use for similar tasks is to make an array or vector of the movie filenames or paths, if you know them beforehand of course. Then use a “nowPlaying” int to keep track of which file is playing. When you get a random int to determine which movie to play next, you can compare the random int with the “nowPlaying” int and get a new random int if they are equal.

// load the first movie or a get a random one...
int nowPlaying = 0;


//later...
int nextMovie = (int)ofRandom( total_number_of_movies );

// if 'nextMovie' equals 'nowPlaying', we run the 'while' loop until we get something that is different
while( nowPlaying == nextMovie ){
    nextMovie = (int)ofRandom( total_number_of_movies );
}
nowPlaying = nextMovie;
bikeMovie.loadMovie( array_of_movies[nowPlaying] );
// etc.

One way to make this a bit more flexible is to use ‘ofDirectory’ and open the directory your movies are located, then pick a random path directly, comparing it to the last path you loaded:

ofDirectory dir;
int total = dir.listDir( ofFilePath::getUserHomeDir() + "/Desktop/movies" );

string newPath = dir.getPath((int)ofRandom( total ));

while( ofIsStringInString(newPath, moviePath) ){
    newPath = dir.getPath((int)ofRandom( total ));
}

moviePath = newPath;

For optimized HD videos, and if you’re using OS X, have a look at the high performance video player examples included with oF as a starting point. To that end, a few folks are working on a wrapper for using AVFoundation in Obj-C; I’ll dig 'em up here if you are interested.

Hope this helps!

Hi @nickhubben,

Thank you for your answer.
This is an interesting method, I will try out. Maybe my code can be a little shorter this way.

One problem I had, though, was to use a same int in different functions, and wasn’t sure were to declare it.
I solved it by making a global variable (declaring it out of any function). I read this isn’t adviced because it can become messy on a big code, but it’s the only solution I found and my code is not that complex so I figured I should be ok.

I also made a second movie object, in order to have the next video load, while the current is playing. A boolean, videoSwap, switches at the end of each video to determine which video object should play.
That way, i thought the transitions could be faster, because the video is already ready to play when triggered. Not sure if I’m right though, what do you think ?

I also used this comparison method in order to never have two identical videos play next to each other.

As of HD optimization, I’m on Windows 7, but I can have access to an OSX computer, and will try it out. It could be usefull, depanding on the platforms on which I would show this project.
I could also be interested in the AVFoundation, even though it’s also only mac. Anything you think is best is always good to know anyways… There must be many ways to make this work with different language and different frameworks, but it’s hard to really know which will really be best and how much of a difference each solution will make (in proportion to how much time it will take to learn and make it work).
I will see the final result and if it isn’t fast enough I’ll dig into those other solutions.

Anyways, here is my new code (functionnal this time :smile: ) if you see anything wrong or unconventional, thanks for letting me know.

#include "math.h"
#include "ofApp.h"

unsigned int randomNumber(0); //first random number for loading a video
unsigned int randomNumberNext(0); //second random number (different, for loading the next video

// number of executions of loadAndPlay - because on 1st execution, both movie object need to be loaded                                                          
unsigned int iter(1);


bool movieSwap(true) ; //boolean to swap which movie object should load while the other play

void ofApp::loadAndPlay () {

    randomNumberNext = floor(ofRandom(21));
    
    //-------------------------------------------------------------------------------------
    // code for first execution of the function (after first execution, iter is incremented)
    if (iter==1) {
        randomNumber = floor(ofRandom(21));
        
        // gets a different random number for the next video to be played
        while (randomNumber == randomNumberNext) {
            randomNumberNext = floor(ofRandom(21));
        }
        
        //switch to load and play the video on first movie object
        switch(randomNumber) {
        case 0:
            bikeMovie.loadMovie("movies/1.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 1:
            bikeMovie.loadMovie("movies/2.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 2:
            bikeMovie.loadMovie("movies/3.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 3:
            bikeMovie.loadMovie("movies/4.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 4:
            bikeMovie.loadMovie("movies/5.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 5:
            bikeMovie.loadMovie("movies/6.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 6:
            bikeMovie.loadMovie("movies/7.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 7:
            bikeMovie.loadMovie("movies/8.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 8:
            bikeMovie.loadMovie("movies/9.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 9:
            bikeMovie.loadMovie("movies/10.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 10:
            bikeMovie.loadMovie("movies/11.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 11:
            bikeMovie.loadMovie("movies/12.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 12:
            bikeMovie.loadMovie("movies/13.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 13:
            bikeMovie.loadMovie("movies/14.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 14:
            bikeMovie.loadMovie("movies/15.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 15:
            bikeMovie.loadMovie("movies/16.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 16:
            bikeMovie.loadMovie("movies/17.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 17:
            bikeMovie.loadMovie("movies/18.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 18:
            bikeMovie.loadMovie("movies/19.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        case 19:
            bikeMovie.loadMovie("movies/20.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        default:
            bikeMovie.loadMovie("movies/21.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            bikeMovie.play();
            break;
        }

        //switch to load the next video on second movie object
        switch(randomNumberNext) {
        case 0:
            bikeMovieTwo.loadMovie("movies/1.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 1:
            bikeMovieTwo.loadMovie("movies/2.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 2:
            bikeMovieTwo.loadMovie("movies/3.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 3:
            bikeMovieTwo.loadMovie("movies/4.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 4:
            bikeMovieTwo.loadMovie("movies/5.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 5:
            bikeMovieTwo.loadMovie("movies/6.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 6:
            bikeMovieTwo.loadMovie("movies/7.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 7:
            bikeMovieTwo.loadMovie("movies/8.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 8:
            bikeMovieTwo.loadMovie("movies/9.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 9:
            bikeMovieTwo.loadMovie("movies/10.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 10:
            bikeMovieTwo.loadMovie("movies/11.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 11:
            bikeMovieTwo.loadMovie("movies/12.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 12:
            bikeMovieTwo.loadMovie("movies/13.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 13:
            bikeMovieTwo.loadMovie("movies/14.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 14:
            bikeMovieTwo.loadMovie("movies/15.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 15:
            bikeMovieTwo.loadMovie("movies/16.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 16:
            bikeMovieTwo.loadMovie("movies/17.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 17:
            bikeMovieTwo.loadMovie("movies/18.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 18:
            bikeMovieTwo.loadMovie("movies/19.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 19:
            bikeMovieTwo.loadMovie("movies/20.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        default:
            bikeMovieTwo.loadMovie("movies/21.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        }

    }
    
    //-------------------------------------------------------------------------------------
    // code for next executions of the function (after first execution, iter is incremented)
    if (iter>1) {
        
         // gets a different random number for the next video to be played
        while (randomNumber == randomNumberNext) {
            randomNumberNext = floor(ofRandom(21));
        }
        
        //the boolean movieSwap is used to load alternatively on the first and second movie buffer
        //while one loads, the other plays -- method used to get faster transitions -- not sure if useful though
        if (movieSwap) {
            
            //switch for loading on second movie object
            switch(randomNumberNext) {
        case 0:
            bikeMovieTwo.loadMovie("movies/1.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 1:
            bikeMovieTwo.loadMovie("movies/2.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 2:
            bikeMovieTwo.loadMovie("movies/3.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 3:
            bikeMovieTwo.loadMovie("movies/4.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 4:
            bikeMovieTwo.loadMovie("movies/5.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 5:
            bikeMovieTwo.loadMovie("movies/6.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 6:
            bikeMovieTwo.loadMovie("movies/7.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 7:
            bikeMovieTwo.loadMovie("movies/8.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 8:
            bikeMovieTwo.loadMovie("movies/9.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 9:
            bikeMovieTwo.loadMovie("movies/10.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 10:
            bikeMovieTwo.loadMovie("movies/11.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 11:
            bikeMovieTwo.loadMovie("movies/12.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 12:
            bikeMovieTwo.loadMovie("movies/13.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 13:
            bikeMovieTwo.loadMovie("movies/14.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 14:
            bikeMovieTwo.loadMovie("movies/15.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 15:
            bikeMovieTwo.loadMovie("movies/16.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 16:
            bikeMovieTwo.loadMovie("movies/17.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 17:
            bikeMovieTwo.loadMovie("movies/18.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 18:
            bikeMovieTwo.loadMovie("movies/19.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        case 19:
            bikeMovieTwo.loadMovie("movies/20.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
        default:
            bikeMovieTwo.loadMovie("movies/21.mov");
            bikeMovieTwo.setLoopState(OF_LOOP_NONE);
            break;
            }
        
        } else {
            
            //switch for loading on first movie object
            switch(randomNumberNext) {
        case 0:
            bikeMovie.loadMovie("movies/1.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 1:
            bikeMovie.loadMovie("movies/2.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 2:
            bikeMovie.loadMovie("movies/3.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 3:
            bikeMovie.loadMovie("movies/4.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 4:
            bikeMovie.loadMovie("movies/5.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 5:
            bikeMovie.loadMovie("movies/6.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 6:
            bikeMovie.loadMovie("movies/7.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 7:
            bikeMovie.loadMovie("movies/8.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 8:
            bikeMovie.loadMovie("movies/9.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 9:
            bikeMovie.loadMovie("movies/10.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 10:
            bikeMovie.loadMovie("movies/11.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 11:
            bikeMovie.loadMovie("movies/12.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 12:
            bikeMovie.loadMovie("movies/13.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 13:
            bikeMovie.loadMovie("movies/14.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 14:
            bikeMovie.loadMovie("movies/15.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 15:
            bikeMovie.loadMovie("movies/16.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 16:
            bikeMovie.loadMovie("movies/17.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 17:
            bikeMovie.loadMovie("movies/18.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 18:
            bikeMovie.loadMovie("movies/19.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        case 19:
            bikeMovie.loadMovie("movies/20.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        default:
            bikeMovie.loadMovie("movies/21.mov");
            bikeMovie.setLoopState(OF_LOOP_NONE);
            break;
        }
        }

    }
    
    //--------------------------------------------
    // this transfers the value for the next movie to the current
    // in order to generate a new number on next execution of loadAndPlay
    // inter is incremented, but is useful only to differentiate first execution
    // when both movie objects need to be loaded
    randomNumber = randomNumberNext ;
    iter++;


}

//--------------------------------------------------------------
void ofApp::setup(){
    ofBackground(0,0,0);

    loadAndPlay();
}

//--------------------------------------------------------------
void ofApp::update(){
    
    // movieSwap is used here to know which video should update (while the other one loads)
    if (movieSwap) {
        bikeMovie.update();
    } else {
        bikeMovieTwo.update();
    }
    
}
//--------------------------------------------------------------
void ofApp::draw(){
    
    // movieSwap is used here to know which video should draw (while the other one loads)
    // and detecting the end of the movie object currently playing
    if (movieSwap) {

        bikeMovie.draw(0,0);
        // code for the end of the movie, triggering the next video to play
        // and  changing the movieSwap boolean
        // then executing again loadAndPlay
        if(bikeMovie.getIsMovieDone()){
                bikeMovieTwo.play();
                movieSwap=false;
                loadAndPlay();
        }
        
    } else {

        bikeMovieTwo.draw(0,0);
        // code for the end of the movie, triggering the next video to play
        // and  changing the movieSwap boolean
        // then executing again loadAndPlay
        if(bikeMovieTwo.getIsMovieDone()){
                bikeMovie.play();
                movieSwap=true;
                loadAndPlay();
        }
    }

}

I certainly do think using 2 video player instances will get you a better experience - even when I use the AVFoundation-based video player I see a frame of nothing while the next video loads.

I also agree that global variables should be used with caution, but this in this case it makes a lot of sense.

One thing that jumps out to me is that if all your video filenames are numbered, you could save a lot of typing by building the filename string dynamically:

string moviePath = "movies/" + ofToString( randomNumber + 1 ) + ".mov";
bikeMovie.loadMovie( moviePath );

Another suggestion would to use an array of 2 video players, and use the global variables to track which player is playing and the last loaded movie ID. I’ve mocked up my suggestion below:

declared in ‘ofApp.h’:

ofVideoPlayer bikeMovies[2];
unsigned int nowPlayer;
unsigned int totalMovies;
unsigned int loadingMovieId;

void playAndPreload();

and in ‘ofApp.cpp’:

void ofApp::setup(){
    ofBackground(0,0,0);

    totalMovies = 21;
    nowPlayer = 0;
    loadingMovieId = 0;

    playAndPreload();
}

//--------------------------------------------------------------

void ofApp::playAndPreload(){

   // PLAY the current movie

   // need to load the first movie : should only happen once
   if( !bikeMovies[nowPlayer].isLoaded() ){
      bikeMovies[nowPlayer].loadMovie( "movies/" + ofToString(loadingMovieId + 1) + ".mov" );
   }

   bikeMovies[nowPlayer].setLoopState(OF_LOOP_NONE);
   bikeMovies[nowPlayer].play();

   cout << "playing: " << bikeMovies[nowPlayer].getMoviePath() << endl;

   //--------------------

   // PRELOAD the next movie

   // get a unique random ID
   int preloadId = floor(ofRandom(totalMovies));
   while (preloadId == loadingMovieId ) {
      preloadId = floor(ofRandom(totalMovies));
   }

   // set the loading movie to the new ID
   loadingMovieId = preloadId;

   // load movie in the player that isn't 'nowPlayer'
   int nextPlayer = nowPlayer == 0 ? 1 : 0;
   bikeMovies[nextPlayer].loadMovie( "movies/" + ofToString(loadingMovieId+1) + ".mov" );

   cout << "loading: " << bikeMovies[nextPlayer].getMoviePath() << "\n" << endl;
}

void ofApp::update(){

   bikeMovies[nowPlayer].update();

   // check for 'isMovieDone' ( *I think this is better to do within the 'update' method* )
   if( bikeMovies[nowPlayer].getIsMovieDone() ){
    
       // stop currently playing video
       bikeMovies[nowPlayer].stop();
    
       // swap video player ID
       nowPlayer = ( nowPlayer == 0 ) ? 1 : 0;

       // make the magic happen
       playAndPreload();
   }
}

//--------------------------------------------------------------
void ofApp::draw(){
   bikeMovies[nowPlayer].draw(0,0);
}

As always, hope this helps!

  • cheers

Hey @nickhubben, this is really neat !
my code was way longer than what was really needed

I also didn’t know this syntax which is very cool

nowPlayer = ( nowPlayer == 0 ) ? 1 : 0;

However, having the “isMovieDone” test in draw was inspired from the videoplayer example of OF. I checked and it is also made this way in the HD videoplayer.
So I tried both solutions, and it appears that when the test is in update, there is a slight lag in transition.
So I can’t really explain why, but I think it’s probably best within draw.

Anyways, this is starting to look really good… I’m always amazed how much you can learn on the internet thanks to people that share knowledge, thanks a lot for your help !

Interesting about getIsMovieDone() - I’ll definitely test that myself as well! You get told all the time that ‘update()’ is where as much non-drawing code should be placed, but it’s certainly not always true.

Glad to help, Lord knows I’ve learned a ton from this forum!