461 lines
16 KiB
Java
461 lines
16 KiB
Java
/*
|
|
Reversound is used to get the music sheet of a piece from a music file.
|
|
Copyright (C) 2014 Gabriel AUGENDRE
|
|
Copyright (C) 2014 Gabriel DIENY
|
|
Copyright (C) 2014 Arthur GAUCHER
|
|
Copyright (C) 2014 Gabriel LEPETIT-AIMON
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
package gui;
|
|
|
|
|
|
import actions.ExpertModeAction;
|
|
import actions.ImportFileAction;
|
|
import actions.QuitAction;
|
|
import actions.ShowInternalFrameAction;
|
|
import generictools.Pair;
|
|
import gui.graphs.GraphicView;
|
|
import processing.AudioInputToBuffer;
|
|
import processing.ProcessControl;
|
|
import processing.buffer.Buffer;
|
|
|
|
import javax.swing.*;
|
|
import java.awt.*;
|
|
import java.awt.event.*;
|
|
import java.beans.PropertyVetoException;
|
|
import java.io.File;
|
|
import java.util.ArrayList;
|
|
|
|
/**
|
|
* La fenêtre principale du programme.
|
|
* @author Gabriel Augendre <gabriel.augendre@insa-lyon.fr>
|
|
*/
|
|
class MainWindow {
|
|
|
|
// Initialize constants
|
|
final private int INITIAL_WIDTH_NON_EXPERT = 700;
|
|
final private int INITIAL_HEIGHT_NON_EXPERT = 120;
|
|
final private int INITIAL_WIDTH_EXPERT = 1200;
|
|
final private int INITIAL_HEIGHT_EXPERT = 500;
|
|
final private boolean EXPERT_MODE_ENABLED_BY_DEFAULT = true;
|
|
|
|
private final ExpertModeAction expertModeAction = new ExpertModeAction(EXPERT_MODE_ENABLED_BY_DEFAULT);
|
|
private final JPanel mainPanel = new JPanel(new BorderLayout(2,2));
|
|
private final JFrame frame = new JFrame();
|
|
private final JMenuBar menuBar = new JMenuBar();
|
|
private final JMenu fileMenu = new JMenu("Fichier");
|
|
private final JToolBar toolBar = new JToolBar();
|
|
private final JMenu displayMenu = new JMenu("Affichage");
|
|
private final JComboBox<String> sourceList = new JComboBox<>();
|
|
private final JButton computeButton = new JButton("Compute");
|
|
private final JButton stopRecordButton = new JButton("Stop recording");
|
|
private final JButton stopComputeButton = new JButton("Stop computing");
|
|
private final JButton resetButton = new JButton("Reset");
|
|
private final JButton enableExpertMode = new JButton(expertModeAction);
|
|
private final ImportFileAction importFileAction = new ImportFileAction(frame, sourceList);
|
|
private final JButton targetFileButton = new JButton(importFileAction);
|
|
private final JDesktopPane expertDisplay = new JDesktopPane();
|
|
private final ArrayList<Pair<JInternalFrame, Integer>> iFrameList = new ArrayList<>();
|
|
private final TimeSlider slider = new TimeSlider();
|
|
private final QuitAction quitAction = new QuitAction(frame);
|
|
private final JMenuItem importItem = new JMenuItem(importFileAction);
|
|
private final JMenuItem quitItem = new JMenuItem(quitAction);
|
|
|
|
private final JMenuItem exportItem = new JMenuItem(new AbstractAction("Exporter") {
|
|
@Override
|
|
public void actionPerformed(ActionEvent e) {
|
|
ProcessControl.instance().launchPostProcess();
|
|
}
|
|
});
|
|
|
|
private final WindowListener exitListener = new WindowAdapter() {
|
|
@Override
|
|
public void windowClosing(WindowEvent e) {
|
|
super.windowClosing(e);
|
|
int confirm = JOptionPane.showOptionDialog(null,
|
|
"Êtes-vous certain de vouloir fermer la fenêtre ?\nToutes les modifications seront perdues.",
|
|
"Confirmer la sortie", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
|
|
if (confirm == 0) {
|
|
ProcessControl.instance().kill();
|
|
frame.dispose();
|
|
}
|
|
}
|
|
};
|
|
|
|
// Set Look and Feel (Mac OS X > Nimbus > System)
|
|
static {
|
|
try {
|
|
boolean b = true;
|
|
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
|
|
UIManager.setLookAndFeel(info.getClassName());
|
|
if ("Mac OS X".equals(info.getName())) {
|
|
b = false;
|
|
break;
|
|
}
|
|
}
|
|
if (b) {
|
|
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
|
|
if ("Nimbus".equals(info.getName())) {
|
|
UIManager.setLookAndFeel(info.getClassName());
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} catch (Exception d) {
|
|
try {
|
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
|
} catch (Exception f) {
|
|
f.printStackTrace(System.err);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Constructeur par défaut, le seul.
|
|
*/
|
|
private MainWindow() {
|
|
|
|
|
|
createMainFrame();
|
|
createExpertDisplay();
|
|
createToolBar();
|
|
createMenuBar();
|
|
|
|
createMagicWindow();
|
|
|
|
frame.setVisible(true);
|
|
mainPanel.repaint();
|
|
|
|
|
|
//ProcessControl.instance().clockTick();
|
|
}
|
|
|
|
/**
|
|
* Création de la fenêtre principale.
|
|
*/
|
|
private void createMainFrame() {
|
|
frame.setTitle("Reversound");
|
|
|
|
// The size depends on the expert mode state
|
|
frame.setSize(
|
|
EXPERT_MODE_ENABLED_BY_DEFAULT?INITIAL_WIDTH_EXPERT:INITIAL_WIDTH_NON_EXPERT,
|
|
EXPERT_MODE_ENABLED_BY_DEFAULT?INITIAL_HEIGHT_EXPERT:INITIAL_HEIGHT_NON_EXPERT);
|
|
if (EXPERT_MODE_ENABLED_BY_DEFAULT) frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
|
|
|
|
// Content for this frame> <
|
|
frame.setContentPane(mainPanel);
|
|
|
|
// Do nothing on close
|
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
|
|
|
// A menu bar (because we need it) ;-)
|
|
frame.setJMenuBar(menuBar);
|
|
|
|
// Resizable depends on the expert mode state
|
|
frame.setResizable(EXPERT_MODE_ENABLED_BY_DEFAULT);
|
|
|
|
// Define what we do if expert mode is enabled or disabled
|
|
expertModeAction.addPropertyChangeListener(evt -> {
|
|
if(evt.getPropertyName().equals(ExpertModeAction.ACTIVE)){
|
|
frame.setResizable((Boolean)evt.getNewValue());
|
|
if (!(Boolean)evt.getNewValue()) {
|
|
frame.setSize(INITIAL_WIDTH_NON_EXPERT, INITIAL_HEIGHT_NON_EXPERT);
|
|
} else {
|
|
frame.setSize(INITIAL_WIDTH_EXPERT, INITIAL_HEIGHT_EXPERT);
|
|
}
|
|
}
|
|
});
|
|
|
|
//Set close operation
|
|
frame.addWindowListener(exitListener);
|
|
}
|
|
|
|
/**
|
|
* Initialize the toolbar and source list.
|
|
*/
|
|
private void createToolBar() {
|
|
|
|
// Put data into source list
|
|
sourceList.addItem("Micro");
|
|
sourceList.setPrototypeDisplayValue("Fichier");
|
|
|
|
// Transmettre au contrôleur la source choisie.
|
|
sourceList.addItemListener(e -> {
|
|
final int INDEX = sourceList.getSelectedIndex();
|
|
System.out.println(sourceList.getItemAt(INDEX));
|
|
|
|
if(INDEX == 0)
|
|
ProcessControl.instance().setInput(ProcessControl.instance().getMainInputID(), AudioInputToBuffer.fromMicro());
|
|
else
|
|
ProcessControl.instance().setInput(
|
|
ProcessControl.instance().getMainInputID(),
|
|
AudioInputToBuffer.fromFile(
|
|
(File) (importFileAction.getValue(ImportFileAction.FILE))
|
|
));
|
|
});
|
|
|
|
//Modifie légèrement le look des boutons, surtout sur Mac OS X
|
|
computeButton.putClientProperty("JButton.buttonType", "textured");
|
|
stopRecordButton.putClientProperty("JButton.buttonType", "segmentedTextured");
|
|
stopRecordButton.putClientProperty("JButton.segmentPosition", "first");
|
|
stopComputeButton.putClientProperty("JButton.buttonType", "segmentedTextured");
|
|
stopComputeButton.putClientProperty("JButton.segmentPosition", "last");
|
|
targetFileButton.putClientProperty("JButton.buttonType", "textured");
|
|
resetButton.putClientProperty("JButton.buttonType", "textured");
|
|
|
|
// Add elements to toolBar
|
|
toolBar.add(computeButton);
|
|
toolBar.add(stopRecordButton);
|
|
toolBar.add(stopComputeButton);
|
|
toolBar.add(resetButton);
|
|
toolBar.add(sourceList);
|
|
toolBar.add(targetFileButton);
|
|
|
|
// Configure le bouton reset
|
|
resetButton.setToolTipText("Réinitialise le programme à son état d'origine.");
|
|
resetButton.addActionListener(e -> reset());
|
|
|
|
// On n'affiche pas les boutons stop au début.
|
|
setStopButtonsState(false);
|
|
|
|
// On relie les boutons au contrôle.
|
|
computeButton.addActionListener(e -> {
|
|
ProcessControl.instance().start();
|
|
setStopButtonsState(true);
|
|
stopRecordButton.setText("Stop recording");
|
|
});
|
|
stopRecordButton.addActionListener(e -> {
|
|
if (stopRecordButton.getText().equals("Stop recording")) {
|
|
stopRecordButton.setText("Record");
|
|
ProcessControl.instance().stopRecord();
|
|
} else {
|
|
stopRecordButton.setText("Stop recording");
|
|
ProcessControl.instance().start();
|
|
}
|
|
});
|
|
stopComputeButton.addActionListener(e -> {
|
|
ProcessControl.instance().stop();
|
|
setStopButtonsState(false);
|
|
});
|
|
|
|
// Add button to enable/disable the expert mode
|
|
{
|
|
setExpertButtonText(EXPERT_MODE_ENABLED_BY_DEFAULT);
|
|
|
|
expertModeAction.addPropertyChangeListener(evt -> {
|
|
if(!evt.getPropertyName().equals(ExpertModeAction.ACTIVE))return;
|
|
setExpertButtonText((boolean)evt.getNewValue());
|
|
});
|
|
|
|
//enableExpertMode.setSelected(EXPERT_MODE_ENABLED_BY_DEFAULT);
|
|
enableExpertMode.putClientProperty("JButton.buttonType", "textured");
|
|
|
|
toolBar.add(enableExpertMode);
|
|
}
|
|
|
|
// Set not draggable
|
|
toolBar.setFloatable(false);
|
|
|
|
// Add the toolbar to the main panel
|
|
mainPanel.add(toolBar,BorderLayout.NORTH);
|
|
}
|
|
|
|
/**
|
|
* Setup the menus and addNote all elements.
|
|
*/
|
|
private void createMenuBar() {
|
|
|
|
// Setup the file menu
|
|
{
|
|
fileMenu.setMnemonic(KeyEvent.VK_F);
|
|
|
|
// Add items : Import, quit
|
|
{
|
|
//importItem.setText("Importer"); //Importer, sous-menu de Fichier
|
|
importItem.setMnemonic(KeyEvent.VK_I);
|
|
fileMenu.add(importItem);
|
|
exportItem.setMnemonic(KeyEvent.VK_E);
|
|
fileMenu.add(exportItem);
|
|
quitItem.setMnemonic(KeyEvent.VK_Q);
|
|
fileMenu.add(quitItem);
|
|
}
|
|
|
|
menuBar.add(fileMenu);
|
|
}
|
|
|
|
// Setup the display menu
|
|
{
|
|
displayMenu.setMnemonic(KeyEvent.VK_A);
|
|
|
|
// Add an item : Enable expert mode
|
|
{
|
|
final JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(expertModeAction);
|
|
menuItem.setSelected(EXPERT_MODE_ENABLED_BY_DEFAULT);
|
|
displayMenu.add(menuItem);
|
|
expertModeAction.addPropertyChangeListener(evt -> {
|
|
if(!evt.getPropertyName().equals(ExpertModeAction.ACTIVE))return;
|
|
menuItem.setSelected((boolean)evt.getNewValue());
|
|
});
|
|
}
|
|
|
|
menuBar.add(displayMenu);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create the expert display.
|
|
*/
|
|
private void createExpertDisplay() {
|
|
// Hide or show the pane if mode enabled by default.
|
|
expertDisplay.setVisible(EXPERT_MODE_ENABLED_BY_DEFAULT);
|
|
|
|
// Add the pane to the main panel
|
|
mainPanel.add(expertDisplay, BorderLayout.CENTER);
|
|
|
|
// When the expertMode is enabled, display the panel
|
|
expertModeAction.addPropertyChangeListener(evt -> {
|
|
if(evt.getPropertyName().equals(ExpertModeAction.ACTIVE)) {
|
|
expertDisplay.setVisible((Boolean) evt.getNewValue());
|
|
}
|
|
});
|
|
|
|
mainPanel.add(slider, BorderLayout.SOUTH);
|
|
}
|
|
|
|
/**
|
|
* Display a buffer in a JInternalFrame. If the frame was previously created, show it. Else, create a new one.
|
|
* @param bufferID The ID of the buffer to be displayed.
|
|
*/
|
|
public void displayBuffer(int bufferID) {
|
|
for (Pair<JInternalFrame, Integer> paire : iFrameList) {
|
|
JInternalFrame iFr = paire.first();
|
|
int bID = paire.second();
|
|
|
|
if (bID == bufferID) {
|
|
if (!iFr.isVisible()) {
|
|
expertDisplay.add(iFr);
|
|
iFr.setVisible(true);
|
|
}
|
|
try {
|
|
iFr.setSelected(true);
|
|
} catch (PropertyVetoException e1) {
|
|
e1.printStackTrace(System.err);
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
Buffer buffer = ProcessControl.instance().getBuffer(bufferID);
|
|
final JInternalFrame iFrame = new JInternalFrame();
|
|
|
|
GraphicView spectreView = GraphicView.createGraphicView(buffer,true);
|
|
addInternalFrame(iFrame, spectreView.getName(), bufferID, spectreView);
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* Ajoute la fenêtre de contrôle à l'affichage Expert.
|
|
* Appelle addInternalFrame(final JInternalFrame IFRAME, final String TITLE, final GraphicView CONTENT).
|
|
*/
|
|
private void createMagicWindow() {
|
|
JInternalFrame iFrame = new JInternalFrame();
|
|
GraphicView v = new ProcessSumUp(this);
|
|
addInternalFrame(iFrame, v.getName(), v);
|
|
}
|
|
|
|
|
|
/**
|
|
* Ajoute une fenêtre à l'affichage Expert et la configure selon les besoins de l'application.
|
|
* @param IFRAME La fenêtre à ajouter.
|
|
* @param TITLE Le titre de la fenêtre.
|
|
* @param BUFFER_ID L'identifiant du buffer à ajouter à la fenêtre pour l'affichage.
|
|
* @param CONTENT Le contenu de la fenêtre.
|
|
*/
|
|
private void addInternalFrame(final JInternalFrame IFRAME, final String TITLE, final int BUFFER_ID, final GraphicView CONTENT) {
|
|
IFRAME.setTitle(TITLE);
|
|
iFrameList.add(new Pair<>(IFRAME, BUFFER_ID));
|
|
IFRAME.setVisible(true);
|
|
expertDisplay.add(IFRAME);
|
|
final int WINDOW_WIDTH = 350;
|
|
IFRAME.setBounds((iFrameList.size() - 2) * 100 + 5, 310, WINDOW_WIDTH, 300);
|
|
IFRAME.setResizable(true);
|
|
IFRAME.setClosable(true);
|
|
IFRAME.setMaximizable(true);
|
|
IFRAME.setContentPane(CONTENT);
|
|
displayMenu.add(new ShowInternalFrameAction(expertDisplay, IFRAME));
|
|
}
|
|
|
|
/**
|
|
* Appelle addInternalFrame avec un BUFFER_ID de -1 (pour la fenêtre de contrôle uniquement.
|
|
* @param IFRAME La fenêtre à ajouter.
|
|
* @param TITLE Le titre de la fenêtre.
|
|
* @param CONTENT Le contenu de la fenêtre.
|
|
*/
|
|
private void addInternalFrame(final JInternalFrame IFRAME, final String TITLE, final GraphicView CONTENT) {
|
|
addInternalFrame(IFRAME, TITLE, -1, CONTENT);
|
|
IFRAME.setClosable(false);
|
|
final int WINDOW_WIDTH = (int)GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds().getWidth();
|
|
IFRAME.setBounds(5,5,WINDOW_WIDTH-10,300);
|
|
}
|
|
|
|
/**
|
|
* Change l'état des boutons stop, compute et de la liste des sources de l'application.
|
|
* @param state False si on souhaite cacher les boutons stop, true sinon.
|
|
*/
|
|
private void setStopButtonsState(final boolean state) {
|
|
stopRecordButton.setVisible(state);
|
|
stopRecordButton.setEnabled(state);
|
|
stopComputeButton.setVisible(state);
|
|
stopComputeButton.setEnabled(state);
|
|
computeButton.setVisible(!state);
|
|
computeButton.setEnabled(!state);
|
|
sourceList.setVisible(!state);
|
|
sourceList.setEnabled(!state);
|
|
targetFileButton.setVisible(!state);
|
|
targetFileButton.setEnabled(!state);
|
|
}
|
|
|
|
/**
|
|
* Change le texte du bouton Expert en fonction d'un booléen.
|
|
* @param b True si le mode expert est désactivé, false sinon.
|
|
*/
|
|
private void setExpertButtonText(boolean b) {
|
|
enableExpertMode.setText(
|
|
!b?
|
|
"Activer le mode expert":
|
|
"Désactiver le mode expert"
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Réinitialise l'application à son état d'origine.
|
|
*/
|
|
private void reset() {
|
|
if (sourceList.getItemCount() > 1)
|
|
sourceList.removeItemAt(1);
|
|
sourceList.setPrototypeDisplayValue("Fichier");
|
|
ProcessControl.instance().reset();
|
|
setStopButtonsState(false);
|
|
}
|
|
|
|
/**
|
|
* Enter point to run this program.
|
|
* @param args None
|
|
*/
|
|
public static void main(String[] args) {
|
|
new MainWindow();
|
|
}
|
|
}
|