// Set the buttons displayed in the panel
  // textFilePath - The path to the sound effect definition file
  // Returns 0 (an error occurred and a new project was opened), 1 (an error occurred), 2 (the
  // project opened normally)
  public int loadFile(String textFilePath) {
    clearBoard();

    // Get the sounds contained in the given project file
    ArrayList<SoundInfo> readSounds = soundManager.readFile(textFilePath);

    // Add buttons to the interface for each sound in the file
    for (int s = 0; s < readSounds.size(); s++) {
      SoundInfo curr = readSounds.get(s);
      if (checkValidKey(curr.getKeyName())) {
        addSound(readSounds.get(s));
      } else {
        soundManager.deleteSound(curr.getKeyCode());
      }
    }

    // Report if an error occurred while opening the project
    // Allow the user to close the project without proceeding
    if (soundManager.getProjectModified()) {
      int choice =
          JOptionPane.showConfirmDialog(
              frame,
              "One or more errors were encountered while reading the project file. "
                  + "The file may be missing, not well-formatted, or not a Cue Masher project file. Do you want to proceed?",
              "Keep Project Open?",
              JOptionPane.YES_NO_OPTION);
      if (choice == JOptionPane.NO_OPTION) {
        openNewProject();
        return 0;
      }
      return 1;
    }
    return 2;
  }
  // Update a sound in the displayed buttons, sound list, and sound file
  // soundClip - An object storing information about the added or updated sound
  public void updateSound(SoundInfo soundClip) {

    // Add the sound to the project
    SoundInfo newSound = soundManager.addSound(soundClip);

    if (newSound != null) {
      // Add a new button to the GUI
      addSound(newSound);
    }

    if (soundManager.getProjectModified()) {

      if (newSound == null) {
        // An existing sound was updated
        // Update the button label and tooltip
        for (int s = 0; s < soundList.size(); s++) {
          BoardButton button = soundList.get(s);
          if (button.getKeyCode() == soundClip.getKeyCode()) {
            button.updateButtonText();
            break;
          }
        }
      }

      // Update the GUI
      frame.setProjectModified();
      refreshSoundBoard();
    }
  }
 // Save the open project if needed
 public boolean saveFile() {
   if (!soundManager.isProjectOpen()) {
     return saveFileAs();
   } else {
     return soundManager.saveFile();
   }
 }
  // Saves the open project to a new file selected by the user
  public boolean saveFileAs() {
    // Filter the file chooser by Cue Masher files
    JFileChooser fileChooser = new JFileChooser();
    fileChooser.setFileFilter(new CueFileFilter());

    // Display the existing file location by default if it exists
    String filePath = soundManager.getProjectFilePath();
    if (filePath != null) {
      File openProjectFile = new File(filePath);
      fileChooser.setSelectedFile(openProjectFile);
    }

    int choice = fileChooser.showSaveDialog(CueMasherPanel.this);
    if (choice == JFileChooser.APPROVE_OPTION) {
      // Get the name of the file the user selected
      File file = fileChooser.getSelectedFile();
      filePath = file.getAbsolutePath().trim();

      // Make sure that it has a Cue Masher file extension
      String cueMasherExt = CueFileFilter.CUE_MASHER_FILE_EXT;
      boolean addExt = false;
      if (filePath.length() < cueMasherExt.length()) addExt = true;
      else {
        String ext =
            filePath.substring(filePath.length() - cueMasherExt.length(), filePath.length());
        if (!ext.equalsIgnoreCase(cueMasherExt)) addExt = true;
      }

      // Add the cue masher file extension if it doesn't exist
      if (addExt) filePath = filePath + cueMasherExt;

      // Save the project to the selected file
      soundManager.setProjectFilePath(filePath);
      return soundManager.saveFile();
    }
    return false;
  }
  // Removes a sound from the interface and sound list
  // keyCode - The keyboard key code associated with the sound
  public void deleteSound(int keyCode) {
    soundManager.deleteSound(keyCode);

    // Search the sound buttons for the button to remove
    for (int s = 0; s < soundList.size(); s++) {
      BoardButton button = soundList.get(s);
      if (button.getKeyCode() == keyCode) {
        // Remove the button from the interface
        remove(button.getButton());
        soundList.remove(s);

        // Update the GUI
        frame.setProjectModified();
        refreshSoundBoard();

        break;
      }
    }
  }
 // Clears the buttons and sounds for a new project
 public void openNewProject() {
   clearBoard();
   soundManager.openNewProject();
 }
 // Reset all Stoppable and Toggleable sounds
 public void resetSounds() {
   soundManager.resetSounds();
 }
 // Returns the sound associated with the given key code
 // keyCode - The keyboard key code associated with the sound to retrieve
 public SoundInfo getSound(int keyCode) {
   return soundManager.getSound(keyCode);
 }