Search code examples
c++carduinoplayback

Error Message using SFEMP3Shield.h Library trying to implement play/pause code


I'm currently hitting a brick wall while trying to edit some code. I'm trying to input a pause/resume piece into the code, so that when the electrode is touched - if playing it will be paused and then consequently be able to be resumed by touching it again.

With my current edit of the code, the track isn't resuming once paused.

I'm learning as I go along so apologies, if it is an glaringly obvious fix. Any help will be greatly appreciated!

Link to library using is here: https://github.com/mpflaga/Sparkfun-MP3-Player-Shield-Arduino-Library

See the code I'm working with below!

// compiler error handling
#include "Compiler_Errors.h"

// touch includes
#include <MPR121.h>
#include <Wire.h>
#define MPR121_ADDR 0x5C
#define MPR121_INT 4

// mp3 includes
#include <SPI.h>
#include <SdFat.h>
#include <FreeStack.h> 
#include <SFEMP3Shield.h>

// mp3 variables
SFEMP3Shield MP3player;
byte result;
int lastPlayed = 0;

// mp3 behaviour defines
#define REPLAY_MODE FALSE  // By default, touching an electrode repeatedly will 
// play the track again from the start each time.
//
// If you set this to FALSE, repeatedly touching an 
// electrode will stop the track if it is already 
// playing, or play it from the start if it is not.

// touch behaviour definitions
#define firstPin 0
#define lastPin 11

// sd card instantiation
SdFat sd;

void setup(){  
    Serial.begin(57600);

    pinMode(LED_BUILTIN, OUTPUT);

    //while (!Serial) ; {} //uncomment when using the serial monitor 
    Serial.println("Bare Conductive Touch MP3 player");

    if(!sd.begin(SD_SEL, SPI_HALF_SPEED)) sd.initErrorHalt();

    if(!MPR121.begin(MPR121_ADDR)) Serial.println("error setting up MPR121");
    MPR121.setInterruptPin(MPR121_INT);

    MPR121.setTouchThreshold(5);
    MPR121.setReleaseThreshold(5);

    result = MP3player.begin();
    MP3player.setVolume(10,10);

    if(result != 0) {
        Serial.print("Error code: ");
        Serial.print(result);
        Serial.println(" when trying to start MP3 player");
    }

}

void loop(){
    readTouchInputs();
}


void readTouchInputs(){

    if (MPR121.touchStatusChanged()) {

        MPR121.updateTouchData();
        // only make an action if we have one or fewer pins touched
        // ignore multiple touches

        if (MPR121.getNumTouches() <= 1) {
            for (int i = 0; i < 12; i++) {  // Check which electrodes were pressed
                if (MPR121.isNewTouch(i)) {

                    //pin i was just touched
                    Serial.print("pin ");
                    Serial.print(i);
                    Serial.println(" was just touched");
                    digitalWrite(LED_BUILTIN, HIGH);

                    if (i <= lastPin && i >= firstPin) {
                        if (MP3player.isPlaying()) {
                            if (lastPlayed == i && !REPLAY_MODE) {
                                // if we're already playing the requested track, stop it
                                // (but only if we're not in REPLAY_MODE)
                                MP3player.pauseMusic();
                                Serial.print("paused_playback");
                                Serial.println(MP3player.getState());
                            }
                            else {
                                // if the track is already paused, resume the track
                                if (MP3player.getState() == paused_playback) {
                                    if (lastPlayed == i) {                
                                        MP3player.resumeMusic();
                                        Serial.print("resuming");
                                        Serial.println(i-firstPin);

                                    } else { 
                                        // if we're already playing a different track (or we're in
                                        // REPLAY_MODE), stop and play the newly requested one
                                        MP3player.stopTrack();
                                        MP3player.playTrack(i-firstPin);
                                        Serial.print("playing track ");
                                        Serial.println(i-firstPin);

                                        // don't forget to update lastPlayed - without it we don't
                                        // have a history
                                        lastPlayed = i;
                                    }
                                }
                            }
                        } else {
                            // if we're playing nothing, play the requested track 
                            // and update lastplayed
                            MP3player.playTrack(i-firstPin);
                            Serial.print("playing track ");
                            Serial.println(i-firstPin);
                            lastPlayed = i;
                        }
                    }    
                } else {
                    if (MPR121.isNewRelease(i)) {
                        Serial.print("pin ");
                        Serial.print(i);
                        Serial.println(" is no longer being touched");
                        digitalWrite(LED_BUILTIN, LOW);
                    } 
                }
            }
        }
    }
}

Thanks Again!

edited code with last played included

// compiler error handling
#include "Compiler_Errors.h"

// touch includes
#include <MPR121.h>
#include <Wire.h>
#define MPR121_ADDR 0x5C
#define MPR121_INT 4

// mp3 includes
#include <SPI.h>
#include <SdFat.h>
#include <FreeStack.h> 
#include <SFEMP3Shield.h>

// mp3 variables
SFEMP3Shield MP3player;
byte result;
int lastPlayed = 0;

// mp3 behaviour defines
#define REPLAY_MODE FALSE  // By default, touching an electrode repeatedly will 
                          // play the track again from the start each time.
                          //
                          // If you set this to FALSE, repeatedly touching an 
                          // electrode will stop the track if it is already 
                          // playing, or play it from the start if it is not.

// touch behaviour definitions
#define firstPin 0
#define lastPin 11


 enum Action {
  DO_NOTHING,
  PLAY,
  PAUSE,
  RESUME,
  STOP_THEN_PLAY
};

Action nextAction(state_m state, int i) {

  if (state == paused_playback && lastPlayed == i) {
    return RESUME;
  }

  if (state != playback) {
    return PLAY;
  }

  if (state == playback && lastPlayed == i){
    return PAUSE;
  }

  if (state == playback) {
    return STOP_THEN_PLAY;
  }

  return DO_NOTHING;
}



// sd card instantiation
SdFat sd;

void setup(){  


  Serial.begin(57600);

  pinMode(LED_BUILTIN, OUTPUT);

  //while (!Serial) ; {} //uncomment when using the serial monitor 
  Serial.println("Bare Conductive Touch MP3 player");

  if(!sd.begin(SD_SEL, SPI_HALF_SPEED)) sd.initErrorHalt();

  if(!MPR121.begin(MPR121_ADDR)) Serial.println("error setting up MPR121");
  MPR121.setInterruptPin(MPR121_INT);

  MPR121.setTouchThreshold(5);
  MPR121.setReleaseThreshold(5);

  result = MP3player.begin();
  MP3player.setVolume(10,10);

  if(result != 0) {
    Serial.print("Error code: ");
    Serial.print(result);
    Serial.println(" when trying to start MP3 player");
   }

}

void loop(){
  readTouchInputs();
}


void readTouchInputs(){
  if(MPR121.touchStatusChanged()){

    MPR121.updateTouchData();
    // only make an action if we have one or fewer pins touched
    // ignore multiple touches

    if(MPR121.getNumTouches()<=1){
   for (int i = 0; i < 12; i++) {  // Check which electrodes were pressed
  if (MPR121.isNewTouch(i)) {

    state = MP3player.getState();
    Action action = nextAction(state, i); // find what to do next

    switch (action) {
    case PLAY:
      Serial.println("play");
      MP3player.playTrack(i-firstPin);
      lastPlayed = i;
      state = playback;
      break;
    case PAUSE:
      Serial.println("pause");
      MP3player.pauseMusic();
      state = paused_playback;
      lastPlayed = i;
      break;
    case RESUME:
      Serial.println("resume");
      MP3player.resumeMusic();
      state = playback;
      break;
    case STOP_THEN_PLAY:
      Serial.println("stop then play");
      MP3player.stopTrack();
      MP3player.playTrack(i-firstPin);
      state = playback;
      lastPlayed = i;
      break;
    default:
      break;
        }
      }
    }
  }
}
}  


Solution

  • Deeply nested if statements are very difficult to follow. I understand that you want to trigger one of four actions (play, pause, resume and stop/play) based on the state of MP3 player, last played track and electrode ID. I suggest you define a function like this to determine an action.

    enum Action {
      DO_NOTHING,
      PLAY,
      PAUSE,
      RESUME,
      STOP_THEN_PLAY
    };
    
    Action nextAction(state_m state, int i) {
    
      if (state == paused_playback && lastPlayed == i) {
        return RESUME;
      }
    
      if (state != playback) {
        return PLAY;
      }
    
      if (state == playback && lastPlayed == i){
        return PAUSE;
      }
    
      if (state == playback) {
        return STOP_THEN_PLAY;
      }
    
      return DO_NOTHING;
    }
    

    Pass the state of MP3 player and the electrode's id to the function. You can then trigger an appropriate action based on the value of action.

    for (int i = 0; i < 12; i++) {  // Check which electrodes were pressed
      if (MPR121.isNewTouch(i)) {
    
        state_m state = MP3player.getState();
        Action action = nextAction(state, i); // find what to do next
    
        switch (action) {
        case PLAY:
          Serial.println("play");
          MP3player.playTrack(i-firstPin);
          lastPlayed = i;
          state = playback;
          break;
        case PAUSE:
          Serial.println("pause");
          MP3player.pauseMusic();
          state = paused_playback;
          lastPlayed = i;
          break;
        case RESUME:
          Serial.println("resume");
          MP3player.resumeMusic();
          state = playback;
          break;
        case STOP_THEN_PLAY:
          Serial.println("stop then play");
          MP3player.stopTrack();
          MP3player.playTrack(i-firstPin);
          state = playback;
          lastPlayed = i;
          break;
        default:
          break;
        }
      }
    }