Help with video mixer logic

I am having a problem with the implementation of a project which uses the video library as well as the serial library and could really use some help. HELP!!

If you like I can also provide a private zoom link and screen share together (Private Message me if you can and I am happy to meet. I am in Saskatoon, Canada).

My goal is as follows:

I have 6 video channels playing in a 3x2 grid. I want to play all videos in tandem in this grid as my default mode, this is called gridMode.

If a button is pressed on the arduino I want to turn off gridMode and go to SpanMode and play a video full screen that correspond to the button # that one has pressed (from 0-5).

There are two layers of logic required.
One to detect the first button being pressed and switching on spanMode and paying the required video.
Once this occurs a secodn logical operation occurs when any button is pressed to return the users to gridMode.

I cannot seem to implement it correctly and have been working around the solution for many days.

Please help me jedi coders of the web… You are my only hope.

My arduino code is a follows:


int chan;
int count;
int lastChan = 6;
boolean push = false;

// constants won't change. They're used here to set pin numbers:

const int buttonPin1 = 2;     // the number of the pushbutton pin
const int buttonPin2 = 3;
const int buttonPin3 = 4;
const int buttonPin4 = 5;
const int buttonPin5 = 6;
const int buttonPin6 = 7;
const int buttonPin7 = 8;
const int buttonPin8 = 9;
const int buttonPin9 = 10;

const int ledPin =  13;      // the number of the LED pin

// these variables will change:
int buttonState1 = 0; // variable for reading the pushbutton status
int buttonState2 = 0;
int buttonState3 = 0;
int buttonState4 = 0;
int buttonState5 = 0;
int buttonState6 = 0;
int buttonState7 = 0;
int buttonState8 = 0;
int buttonState9 = 0;

void setup() {
  Serial.begin(9600);
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  //  receiver = new ValueReceiver(this, serial);
  //  initialize the pushbutton pin as an input:
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  pinMode(buttonPin5, INPUT);
  pinMode(buttonPin6, INPUT);


}

void loop() {

  allButtons();     // check if the pushbutton is pressed. If it is, the buttonState is HIGH:

  if (buttonState1 == HIGH && count == 0) {
    count++;
    chan = 0;
    Serial.write(chan);
  }
  else if (buttonState1 == HIGH && count == 1 && lastChan != 6) {
    chan = 6;
    Serial.write(chan);
    count = 0;
  }

  else if (buttonState2 == HIGH) {
    chan = 1;
    if (chan != lastChan) {
      Serial.write(chan);
    }
  }
  else if (buttonState3 == HIGH) {
    chan = 2;
    if (chan != lastChan) {
      Serial.write(chan);
    }
  }
  else if (buttonState4 == HIGH) {
    chan = 3;
    if (chan != lastChan) {
      Serial.write(chan);
    }
  }
  else if (buttonState5 == HIGH ) {
    chan = 4;
    if (chan != lastChan) {
      Serial.write(chan);
    }
  }
  else if (buttonState6 == HIGH) {
    chan = 5;
    if (chan != lastChan) {
      Serial.write(chan);
    }
  }

  delay(50);
  lastChan = chan;

}

void allButtons() {
  buttonState1 = digitalRead(buttonPin1);
  buttonState2 = digitalRead(buttonPin2);
  buttonState3 = digitalRead(buttonPin3);
  buttonState4 = digitalRead(buttonPin4);
  buttonState5 = digitalRead(buttonPin5);
  buttonState6 = digitalRead(buttonPin6);
}

My Processing code (P4) is as follows. At the moment the code requires the arduino to run as well as 6 files in data named v0.mp4 - v5.mp4 (one can rename any .mp4 to this aim).

Any help is hugely appreaciated.

import processing.serial.*;
import processing.video.*;

Movie[] vid;
Serial arduino;
String[] name;
int numVid = 6;  //number of videos files
Boolean spanMode = false;
Boolean goTime = false;
long timeStamp, mark;  //  SavedTime when a button is pressed and times out when time has elapsed
int period = 3000;  // 3000 milliseconds = 3 seconds max time to play any channel before witching back to chan 6
int val, lastVal;
int mid, left, right;
float fRate = 29.97;
PImage curse;  //custom cursor
PGraphics cible;  //target shaped cursor


void setup() {
  //fullScreen(P2D, SPAN);  //use this for multi screen
  fullScreen(P2D, 1);
  //size(300, 300, P2D);
  surface.setTitle("Rasputin!");
  surface.setResizable(true);
  smooth();
  //  frameRate(29.97);  //use this to set a cap pn the overall program frameRate. Number in Frames per second.
  makeArduinoCOM();  //  SEB: create a way to find COM 3 or COM4 port on others PCs.
  vid = new Movie[numVid];
  name = new String[numVid];

  if (val == 6) {
    spanMode = !spanMode;
  }

  for (int i = 0; i < numVid; i++) {
    name[i] = "v" + str(i) + ".mp4";
  }
  printArray(name);
  loadVideos();      //initialize settings for composition see settings tab above.
}

void draw() {
  //background(0);
  vidAvail();     // updates video buffer
  defineGridBounds();  //  Sets the values for hoverSelect (mid,left,right). Run in case the surface size changes.

  if (val == 6) {
    spanMode = !spanMode;
  }
  
  if (!spanMode) {
    gridSpan();
  }
  
  singleChan(readArduino());
  println("val is now = " + val);
}


void makeArduinoCOM() {
  print("Serial USB ports are as follows: \n");
  printArray(Serial.list());
  String portName = Serial.list()[1];   //add a check if null command check if null
  print("Port set to " + portName + " \n");
  arduino = new Serial(this, portName, 9600);
}

void loadVideos() {
  for (int i = 0; i < numVid; i++) {
    vid[i] = new Movie(this, name[i]);
    vid[i].frameRate(fRate);
    vid[i].loop();
  }
  customCursor();      // set the cursor to a custom image
  defineGridBounds();  // sets the size of the videos to fit the current screen resolution
}

void vidAvail() {
  while (vid[0].available() || vid[1].available() || vid[2].available() || vid[3].available() || vid[4].available() || vid[5].available() ) {
    vid[0].read();
    vid[1].read();
    vid[2].read();
    vid[3].read();
    vid[4].read();
    vid[5].read();
  }
}

void customCursor() {
  cible = createGraphics(32, 32);
  cible.beginDraw();
  cible.clear();
  for (int i=0; i < 5; i++) {
    cible.noFill();
    cible.smooth(8);
    cible.stroke(255, i*33, 0);
    cible.ellipseMode(CENTER);
    cible.ellipse(16, 16, i*5, i*5);
  }
  cible.endDraw();
  curse = createImage(32, 32, ARGB);
  curse.pixels = cible.pixels;
  cursor(curse);
}

void defineGridBounds() {
  mid = height/2;
  left = width/3;
  right = width * 2/3;
}

int readArduino() {
  if ( arduino.available() > 0) {  // If data is available, read it and store it in val
    val = arduino.read();
    //spanMode = !spanMode;
    println(val + " : " + millis());
  }
  return val;
}

void gridSpan() {
  //implement a ways to maintain aspect ratios of input videos to avoid videos distortions,
  //a secondary values based on left,right and mid must be accesible that is mapped to the correct video aspect ratio.
  //map video width and height to left and mid and ensure they are mapped correctly without distortions
  image(vid[0], 0, 0, left, mid);
  image(vid[1], left, 0, left, mid);
  image(vid[2], right, 0, left, mid);
  image(vid[3], 0, mid, left, mid);
  image(vid[4], left, mid, left, mid);
  image(vid[5], right, mid, left, mid);
}

void singleChan(int _x) {
  //goTime = true;
  if (val == 6) {
    spanMode = false;
  }

  if (spanMode && val != 6) {
    image(vid[_x], 0, 0, width, height);
  }
}

I finally found a suitable solution for my needs.

Here it is:

import processing.serial.*;
import processing.video.*;

Movie[] vid;
Serial arduino;

String[] name;
int numVid = 6;  //number of videos files
int count;
Boolean activated = false;
Boolean goTime = false;
long timeStamp, mark;  //  SavedTime when a button is pressed and times out when time has elapsed
int period = 3000;  // 3000 milliseconds = 3 seconds max time to play any channel before witching back to chan 6
int val;
int lastVal;
int mid, left, right;
float fRate = 29.97;
PImage curse;  //custom cursor
PGraphics cible;  //target shaped cursor


void setup() {
  //fullScreen(P2D, SPAN);  //use this for multi screen
  fullScreen(P2D, 1);
  //size(300, 300, P2D);
  surface.setTitle("Rasputin!");
  surface.setResizable(true);
  smooth();
  //  frameRate(29.97);  //use this to set a cap pn the overall program frameRate. Number in Frames per second.
  makeArduinoCOM();  //  SEB: create a way to find COM 3 or COM4 port on others PCs.
  vid = new Movie[numVid];
  name = new String[numVid];

  for (int i = 0; i < numVid; i++) {
    name[i] = "v" + str(i) + ".mp4";
  }

  printArray(name);
  loadVideos();      //initialize settings for composition see settings tab above.
}

void draw() { 
  vidAvail();     // updates video buffer
  defineGridBounds();  //  Sets the values for hoverSelect (mid,left,right). Run in case the surface size changes.
  modeSelect();
}


void makeArduinoCOM() {
  print("Serial USB ports are as follows: \n");
  printArray(Serial.list());
  String portName = Serial.list()[1];   //add a check if null command check if null
  print("Port set to " + portName + " \n");
  arduino = new Serial(this, portName, 9600);
}

void loadVideos() {
  for (int i = 0; i < numVid; i++) {
    vid[i] = new Movie(this, name[i]);
    vid[i].frameRate(fRate);
    vid[i].loop();
  }
  customCursor();      // set the cursor to a custom image
  defineGridBounds();  // sets the size of the videos to fit the current screen resolution
}

void vidAvail() {
  while (vid[0].available() || vid[1].available() || vid[2].available() || vid[3].available() || vid[4].available() || vid[5].available() ) {
    vid[0].read();
    vid[1].read();
    vid[2].read();
    vid[3].read();
    vid[4].read();
    vid[5].read();
  }
}

void customCursor() {
  cible = createGraphics(32, 32);
  cible.beginDraw();
  cible.clear();
  for (int i=0; i < 5; i++) {
    cible.noFill();
    cible.smooth(8);
    cible.stroke(255, i*33, 0);
    cible.ellipseMode(CENTER);
    cible.ellipse(16, 16, i*5, i*5);
  }
  cible.endDraw();
  curse = createImage(32, 32, ARGB);
  curse.pixels = cible.pixels;
  cursor(curse);
}

void defineGridBounds() {
  mid = height/2;
  left = width/3;
  right = width * 2/3;
}

void serialEvent(Serial arduino) {
  val = arduino.read();
  println("val received = " + val + " " + "at " + millis() + ".");
  if (val <= 5) {
  count++;
  }
}

void modeSelect() {
  if (count == 0) {
    activated = false;
    gridSpan();
  } else if (count == 1) {
    activated = true;
    println("PLAY a full screen video!");
    spanMode(val);
  } else if (count >= 2) {
    activated = false;
    count = 0;
  }
}
void gridSpan() {
  //implement a ways to maintain aspect ratios of input videos to avoid videos distortions,
  //a secondary values based on left,right and mid must be accesible that is mapped to the correct video aspect ratio.
  //map video width and height to left and mid and ensure they are mapped correctly without distortions
  image(vid[0], 0, 0, left, mid);
  image(vid[1], left, 0, left, mid);
  image(vid[2], right, 0, left, mid);
  image(vid[3], 0, mid, left, mid);
  image(vid[4], left, mid, left, mid);
  image(vid[5], right, mid, left, mid);
}

void spanMode(int _x) {
  //goTime = true;
  if (activated && val < 6) {
    image(vid[_x], 0, 0, width, height);
  }
}


/*

int chan;
int lastChan;
boolean push = false;

// constants won't change. They're used here to set pin numbers:

const int buttonPin1 = 2;     // the number of the pushbutton pin
const int buttonPin2 = 3;
const int buttonPin3 = 4;
const int buttonPin4 = 5;
const int buttonPin5 = 6;
const int buttonPin6 = 7;
const int buttonPin7 = 8;
const int buttonPin8 = 9;
const int buttonPin9 = 10;

const int ledPin =  13;      // the number of the LED pin

// these variables will change:
int buttonState1 = 0; // variable for reading the pushbutton status
int buttonState2 = 0;
int buttonState3 = 0;
int buttonState4 = 0;
int buttonState5 = 0;
int buttonState6 = 0;
int buttonState7 = 0;
int buttonState8 = 0;
int buttonState9 = 0;

void setup() {
  Serial.begin(9600);
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  //  receiver = new ValueReceiver(this, serial);
  //  initialize the pushbutton pin as an input:
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  pinMode(buttonPin5, INPUT);
  pinMode(buttonPin6, INPUT);


}

void loop() {

  allButtonsread();     // check if the pushbutton is pressed. If it is, the buttonState is HIGH:

  if (buttonState1 == HIGH) {
    chan = 0;
    Serial.write(chan);
  }
  else if (buttonState2 == HIGH) {
    chan = 1;
    Serial.write(chan);
  }
  else if (buttonState3 == HIGH) {
    chan = 2;
    Serial.write(chan);
  }
  else if (buttonState4 == HIGH) {
    chan = 3;
    Serial.write(chan);
  }
  else if (buttonState5 == HIGH ) {
    chan = 4;
    Serial.write(chan);
  }
  else if (buttonState6 == HIGH) {
    chan = 5;
    Serial.write(chan);
  }
  delay(150);
  lastChan = chan;

}

void allButtonsread() {
  buttonState1 = digitalRead(buttonPin1);
  buttonState2 = digitalRead(buttonPin2);
  buttonState3 = digitalRead(buttonPin3);
  buttonState4 = digitalRead(buttonPin4);
  buttonState5 = digitalRead(buttonPin5);
  buttonState6 = digitalRead(buttonPin6);
}


  
/*
 Arduino code:

int chan;
int lastChan;
boolean push = false;

// constants won't change. They're used here to set pin numbers:

const int buttonPin1 = 2;     // the number of the pushbutton pin
const int buttonPin2 = 3;
const int buttonPin3 = 4;
const int buttonPin4 = 5;
const int buttonPin5 = 6;
const int buttonPin6 = 7;
const int buttonPin7 = 8;
const int buttonPin8 = 9;
const int buttonPin9 = 10;

const int ledPin =  13;      // the number of the LED pin

// these variables will change:
int buttonState1 = 0; // variable for reading the pushbutton status
int buttonState2 = 0;
int buttonState3 = 0;
int buttonState4 = 0;
int buttonState5 = 0;
int buttonState6 = 0;
int buttonState7 = 0;
int buttonState8 = 0;
int buttonState9 = 0;

void setup() {
  Serial.begin(9600);
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  //  receiver = new ValueReceiver(this, serial);
  //  initialize the pushbutton pin as an input:
  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  pinMode(buttonPin5, INPUT);
  pinMode(buttonPin6, INPUT);


}

void loop() {

  allButtonsread();     // check if the pushbutton is pressed. If it is, the buttonState is HIGH:

  if (buttonState1 == HIGH) {
    chan = 0;
    Serial.write(chan);
  }
  else if (buttonState2 == HIGH) {
    chan = 1;
    Serial.write(chan);
  }
  else if (buttonState3 == HIGH) {
    chan = 2;
    Serial.write(chan);
  }
  else if (buttonState4 == HIGH) {
    chan = 3;
    Serial.write(chan);
  }
  else if (buttonState5 == HIGH ) {
    chan = 4;
    Serial.write(chan);
  }
  else if (buttonState6 == HIGH) {
    chan = 5;
    Serial.write(chan);
  }
  delay(150);
  lastChan = chan;

}

void allButtonsread() {
  buttonState1 = digitalRead(buttonPin1);
  buttonState2 = digitalRead(buttonPin2);
  buttonState3 = digitalRead(buttonPin3);
  buttonState4 = digitalRead(buttonPin4);
  buttonState5 = digitalRead(buttonPin5);
  buttonState6 = digitalRead(buttonPin6);
}



*/