1
votes

We are trying to create an interactive video player, which contains 10 short video files, but it has to have a certain functionality: 1st video playing automatically from beginning. Once it is finished, the user must chose by an arrow click, which video to play next - there's two options. Once chosen option of video is finished to play, next video must start to play automatically. Once this video is done playing, there must be another choice between two other videos, just as the first time, and it goes on, till it ends by 10th video playing automatically.

There's two major problems - after first video being played and first choice being done, third video, that suppose to play automatically, doesn't play and the whole application gets stuck. Also, while the first default video is playing, keys pressed are triggering other two videos to play, meanwhile they suppose to play ONLY when the first video is done playing. To make it more understandable, the structure of video playing order and interactivity points, here's the illustration of it:

Interactive video player structure

We hope we formulate the problem so it is easy to understand. Any help or tips would be highly appreciated.

import processing.video.*;

Movie [] mov = new Movie [10];

Boolean playMovie0 = true;
Boolean playMovie1 = false;
Boolean playMovie2 = false;
Boolean playMovie3 = false;
Boolean playMovie4 = false;
Boolean playMovie5 = false;
Boolean playMovie6 = false;
Boolean playMovie7 = false;
Boolean playMovie8 = false;
Boolean playMovie9 = false;

void setup (){
  size (810, 540);

  mov [0] = new Movie (this, "Vid0.mp4");
  mov [1] = new Movie (this, "Vid1.mp4");
  mov [2] = new Movie (this, "Vid2.mp4");
  mov [3] = new Movie (this, "Vid3.mp4");
  mov [4] = new Movie (this, "Vid4.mp4");
  mov [5] = new Movie (this, "Vid5.mp4");
  mov [6] = new Movie (this, "Vid6.mp4");
  mov [7] = new Movie (this, "Vid7.mp4");
  mov [8] = new Movie (this, "Vid8.mp4");
  mov [9] = new Movie (this, "Vid9.mp4");

  mov[0].play();
}

void draw (){
  if (playMovie0 == true){
    image(mov[0], 0, 0, width, height);

    if (mov[0].time() >= mov[0].duration()){
      mov[0].stop();
      playMovie0 =false;
    }
    if (key == CODED){
      if (keyCode == LEFT){
        playMovie1 = true;
        mov[1].play();
        image(mov[1], 0, 0, width, height);
      } else if (keyCode == RIGHT){
        playMovie2 = true;
        mov[2].play();
        image(mov[2], 0, 0, width, height);
      }
    }
  }

  if (mov[1].time() >= mov[1].duration()){
    mov[1].stop();
    playMovie1 = false;
    playMovie3 = true;
  } else if (mov[2].time() >= mov[2].duration()){
    mov[2].stop();
    playMovie2 = false;
    playMovie3 = true;
  }

  if (playMovie0 == false && playMovie1 == false && playMovie2 == false && playMovie3 == true){
    mov[3].play();
    image(mov[3], 0, 0, width, height);

    if (mov[3].time() >= mov[3].duration()){
      mov[3].stop();
      playMovie3 = false;
    }

    if (key == CODED){
      if (keyCode == LEFT){
        playMovie4 = true;
        mov[4].play();
        image(mov[4], 0, 0, width, height);
      } else if (keyCode == RIGHT){
        playMovie5 = true;
        mov[5].play();
        image(mov[5], 0, 0, width, height);
      }
    }
  }

  if (mov[4].time() >= mov[4].duration()){
    mov[4].stop();
    playMovie4 = false;
    playMovie6 = true;
  } else if (mov[5].time() >= mov[5].duration()){
    mov[5].stop();
    playMovie5 = false;
    playMovie6 = true;
  }

  if (playMovie0 == false && playMovie1 == false && playMovie2 == false &&
    playMovie3 == false && playMovie4 == false && playMovie5 == false && playMovie6 == true) {

    mov[6].play();
    image(mov[6], 0, 0, width, height);

    if (mov[6].time() >= mov[6].duration()){
      mov[6].stop();
      playMovie6 = false;
    }

    if (key == CODED){
      if (keyCode == LEFT){
        playMovie7 = true;
        mov[7].play();
        image(mov[7], 0, 0, width, height);
      } else if (keyCode == RIGHT){
        playMovie8 = true;
        mov[8].play();
        image(mov[8], 0, 0, width, height);
      }
    }
  }

  if (mov[7].time() >= mov[7].duration()){
    mov[7].stop();
    playMovie7 = false;
    playMovie9 = true;
  } else if (mov[8].time() >= mov[8].duration()){
    mov[8].stop();
    playMovie8 = false;
    playMovie9 = true;
  }

  if (playMovie0 == false && playMovie1 == false && playMovie2 == false &&
    playMovie3 == false && playMovie4 == false && playMovie5 == false &&
    playMovie6 == false && playMovie7 == false && playMovie8 == false && playMovie9 == true){

    mov[9].play();
    image(mov[9], 0, 0, width, height);
  }
}

void movieEvent (Movie m)
{
  m.read();
}
1

1 Answers

0
votes

Please carefully read this similar answer on the topic of playing back a list of videos. It covers a couple of handy tips such as not repeating yourself and using arrays.

The only part that makes your question different is managing states, which at the moment are at least 3:

  1. playing an automatic video
  2. presenting a next video select screen
  3. playing a selected video

These states alternate until the end of the playlist is reached. This is known as a finite state machine and making one isn't as hard as it may seem. There a few 'ingredients' you'll need:

  1. A variable to keep track of the current state
  2. A list of variables for each separate state;

Once you have these, you simply need to check what the current state is and based on the decisions available in this state, select the next.

For example in the automatic video playing, a decision can be made at the end of the video:

  • is it the last video
  • if not, go to the select screen

On the select screen, the decision is based on key input:

  • if left is pressed, play the next video
  • if right is pressed, play the 2nd video after the current

and so on.

Here is this concept as code, with comments explaining each part:

import processing.video.*;

int numMovies = 10;//total number of movies
Movie [] mov = new Movie [numMovies];//a list of all the movie objects, currently not initialized

int currentMovieIndex = 0;//index of the movie currently playing
int movieIndexOffset;//the offset in index between the selected/automatic movies (skip 1 or 2 videos?)

//application states
int STATE_WAITING_FOR_KEY = 0;
int STATE_PLAYING_SELECTED_MOVIE = 1;
int STATE_PLAYING_AUTOMATIC_MOVIE = 2;

int currentState = STATE_PLAYING_AUTOMATIC_MOVIE;
//just for debugging:
String[] stateLabels = {"waiting for key","playing selected movie","playing automatic movie"};

//a 'magic number' helpful to find out when a movie finishes playing
float movieEndDuration = 0.039719;

String selectScreenText = "Use the left or right keys to select the next video";


void setup (){
  size (810, 540);
  noStroke();
  textSize(24);

  for(int i = 0 ; i < numMovies; i++){
    //initialize each movie object in the list
    mov[i] = new Movie(this, "vid"+i+".mp4");
  }

  //start playback
  mov[currentMovieIndex].play();
}

void draw (){
  if(currentState == STATE_WAITING_FOR_KEY) drawWaitKeyState();
  if(currentState == STATE_PLAYING_AUTOMATIC_MOVIE || 
     currentState == STATE_PLAYING_SELECTED_MOVIE) drawMovie();
}
//rendering
void drawWaitKeyState(){
  background(0);
  text(selectScreenText,(width-textWidth(selectScreenText)) * 0.5,height * 0.5);  
}
void drawMovie(){
  background(0);
  image(mov[currentMovieIndex],0,0);
}
//events
void keyReleased(){
  if(currentState == STATE_WAITING_FOR_KEY){
    if(keyCode == LEFT)  {
      movieIndexOffset = 1;//current movie index plus 1
      playSelectedMovie();
    }
    if(keyCode == RIGHT) {
      movieIndexOffset = 2;//current movie index plus 2
      playSelectedMovie();//current movie index plus 2
    }
  }
}
/*
  A - auto
  S - selected
  movie index type: A - S - A - S - A - S - A
  movie index:      0 - 1 - 3 - 4 - 6 - 7 - 9
                      - 2 /     5 /   - 8 / 
*/
void playSelectedMovie(){
  currentState = STATE_PLAYING_SELECTED_MOVIE;
  currentMovieIndex += movieIndexOffset;
  mov[currentMovieIndex].play();
  println("selection made, playing movie at index " + currentMovieIndex);
}
void movieEvent (Movie m)
{
  if(currentState == STATE_PLAYING_AUTOMATIC_MOVIE || currentState == STATE_PLAYING_SELECTED_MOVIE){
    m.read();
    //handy for debugging movie end
//    println(m.time() + " / " + m.duration() + " / " + (m.time() + movieEndDuration));
    //hacky check movie end 
    if((m.time() + movieEndDuration) >= m.duration()){
        println("movie at index " + currentMovieIndex + " finished playback, current state: " + stateLabels[currentState]);

        //if the current state is an automatic video, the next state will be a choice screen
        if(currentState == STATE_PLAYING_AUTOMATIC_MOVIE) {
          //if it's not the last movie
          if(currentMovieIndex < numMovies-1){
            currentState = STATE_WAITING_FOR_KEY;
          }else{
            println("all movies finished playing, either reset to first movie or set an end screen");
          }
        }
        //if the current state is a selected video, the next state will be an automatic video
        if(currentState == STATE_PLAYING_SELECTED_MOVIE) {
          currentState = STATE_PLAYING_AUTOMATIC_MOVIE;
          //reverse 1 or 2 by subtracting from 3 
          //if the previous choice was to skip 2, automatically skip 1 ( 3 - 2 = 1), if the previous choice was to skip 1, automatically skip 2 ( 3 - 1 = 2) 
          int automaticOffset = 3 - movieIndexOffset; 
          currentMovieIndex += automaticOffset;
          mov[currentMovieIndex].play();
          println("automatically playing movie at index " + currentMovieIndex);
        }
    }
  }
}