package soundtest;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import org.jogamp.java3d.BackgroundSound;
import org.jogamp.java3d.BoundingBox;
import org.jogamp.java3d.Bounds;
import org.jogamp.java3d.BranchGroup;
import org.jogamp.java3d.Canvas3D;
import org.jogamp.java3d.MediaContainer;
import org.jogamp.java3d.audioengines.javasound.JavaSoundMixer;
import org.jogamp.java3d.utils.universe.SimpleUniverse;
import org.jogamp.vecmath.Point3d;

/**
 * Test scene demonstrating BackgroundSound (WAV and AU files supported).
 * 
 * Note: tested with Java3D 1.7.1 using Java 1.8 and 20.0.1
 *       OS: Windows 10
 * 
 * Click on button to start sound.
 * 
 * @author basti
 */
public class BackgroundSoundTest extends JFrame {
    
    public static void main(String[] args) {
        new BackgroundSoundTest().start();
    }
    
    /* Path to sound file. WAV and AU files are supported */
    private final String file = "myFile.wav";
    
    private final Canvas3D canvas;
    private final BackgroundSound backgroundSound;
    private final SimpleUniverse simpleUniverse;
    private final JButton playSound;
    
    public BackgroundSoundTest() {
        System.setProperty("sun.awt.noerasebackground", "true");
        
        this.canvas = buildCanvas3D();
        this.simpleUniverse = new SimpleUniverse(canvas);
        this.playSound = new JButton("play sound");
        this.backgroundSound = new BackgroundSound();
        
        init();
        initFrame();
        simpleUniverse.addBranchGraph(buildRoot());
    }

    private void addSoundMixer() {
        /* This is needed to hear sound. No exception thrown without this line! */
        new JavaSoundMixer(simpleUniverse.getViewer().getPhysicalEnvironment())
                .initialize();
    }

    private BranchGroup buildRoot() {
        BranchGroup root = new BranchGroup();
        
        root.addChild(backgroundSound);
        root.compile();
        return root;
    }

    private void initBackgroundSound(String file) {
        float initialGain = 1.0f;
        MediaContainer mediaContainer = new MediaContainer("file:" + file);
        Bounds bounds = new BoundingBox(
            new Point3d(-100, -100, -100),
            new Point3d(100, 100, 100)
        );
        
        mediaContainer.setCacheEnable(true);
        backgroundSound.setSoundData(mediaContainer);
        backgroundSound.setInitialGain(initialGain);
        backgroundSound.setCapability(BackgroundSound.ALLOW_ENABLE_WRITE);
        
        /* Has to be schedulingBounds, setBounds did not work for me. */
        backgroundSound.setSchedulingBounds(bounds);
        
        //backgroundSound.setLoop(Sound.INFINITE_LOOPS); // played indefinitely
        backgroundSound.setLoop(0); //played once
        
        System.out.println("file loaded..." + file);
    }
    
    private Canvas3D buildCanvas3D() {
        return new Canvas3D(SimpleUniverse.getPreferredConfiguration());
    }
    
    private void start() {
        setVisible(true);
    }
    
    private void initFrame() {
        setTitle("BackgroundSound Test");
        setPreferredSize(new Dimension(500, 500));
        pack();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    private void init() {
        playSound.addActionListener(event -> {
            //playing sound
            backgroundSound.setEnable(true);
        });
        
        addComponents();
        addSoundMixer();
        initBackgroundSound(file);
    }

    private void addComponents() {
        JPanel southPanel = new JPanel(new FlowLayout());
        
        southPanel.add(playSound);
        add(canvas, BorderLayout.CENTER);
        add(southPanel, BorderLayout.SOUTH);
    }
}