// Path: src/webcamstudio/WebcamStudio.java
// public static int audioFreq = 22050;
// 
// Path: src/webcamstudio/components/Viewer.java
// public class Viewer extends javax.swing.JPanel {
//     GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
//     GraphicsDevice device = env.getDefaultScreenDevice();
//     GraphicsConfiguration config = device.getDefaultConfiguration();
//     private BufferedImage img = config.createCompatibleImage(320, 240, BufferedImage.TYPE_INT_ARGB);
//     private int audioLeft = 0;
//     private int audioRight=0;
// 
//     /** Creates new form Viewer */
//     public Viewer() {
//         initComponents();
//     }
// 
//     public void setImage(BufferedImage image) {
//         
//         img=image;
//         
//     }
//          
//     public void setAudioLevel(int l, int r){
//         audioLeft = l;
//         audioRight = r;
//     }
//     @Override
//     public void paintComponent(Graphics g) {
//         Graphics2D graph = (Graphics2D) g;
//         
//         graph.setRenderingHint(java.awt.RenderingHints.KEY_INTERPOLATION, 
//                                java.awt.RenderingHints.VALUE_INTERPOLATION_BILINEAR);
//         graph.setRenderingHint(java.awt.RenderingHints.KEY_RENDERING,
//                                java.awt.RenderingHints.VALUE_RENDER_SPEED);
//         graph.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING,
//                                java.awt.RenderingHints.VALUE_ANTIALIAS_OFF);
//         graph.setRenderingHint(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING,
//                                java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
//         graph.setRenderingHint(java.awt.RenderingHints.KEY_FRACTIONALMETRICS,
//                                java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
//         graph.setRenderingHint(java.awt.RenderingHints.KEY_COLOR_RENDERING,
//                                java.awt.RenderingHints.VALUE_COLOR_RENDER_SPEED);
//         graph.setRenderingHint(java.awt.RenderingHints.KEY_DITHERING,
//                                java.awt.RenderingHints.VALUE_DITHER_DISABLE);
// 
//         int w = this.getWidth();
//         int h = this.getHeight();
//         graph.setBackground(Color.BLACK);
//         graph.clearRect(0, 0, w, h);
//         if (img != null) {
//             int imgWidth = h * img.getWidth() / img.getHeight();
//             int border = (w - imgWidth) / 2;
//             graph.drawImage(img, border, 0, imgWidth, h, null);
//         } else {
//             graph.setColor(Color.WHITE);
//             graph.drawString("No Image",10,10);
//         }
//         if (audioLeft > 0 || audioRight > 0){
//             graph.setColor(Color.green);
//             graph.fillRect(0, h - audioLeft * h / 128, 10, audioLeft * h / 128);
//             graph.fillRect(w-10, h - audioRight * h / 128, 10, audioRight * h / 128);
//         }
//     }
// 
//     /** This method is called from within the constructor to
//      * initialize the form.
//      * WARNING: Do NOT modify this code. The content of this method is
//      * always regenerated by the Form Editor.
//      */
//     @SuppressWarnings("unchecked")
//     // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
//     private void initComponents() {
// 
//         setPreferredSize(new java.awt.Dimension(30, 29));
// 
//         javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
//         this.setLayout(layout);
//         layout.setHorizontalGroup(
//             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
//             .addGap(0, 41, Short.MAX_VALUE)
//         );
//         layout.setVerticalGroup(
//             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
//             .addGap(0, 39, Short.MAX_VALUE)
//         );
//     }// </editor-fold>//GEN-END:initComponents
//     // Variables declaration - do not modify//GEN-BEGIN:variables
//     // End of variables declaration//GEN-END:variables
// }


import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import static java.util.concurrent.Executors.newCachedThreadPool;
import javax.sound.sampled.AudioFormat;
import static javax.sound.sampled.AudioSystem.getSourceDataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import static webcamstudio.WebcamStudio.audioFreq;
import webcamstudio.components.Viewer;
import static webcamstudio.util.Tools.sleep;
        return instance;
    }
    
    boolean stopMe = false;
    public boolean stopMePub = stopMe;
    private SourceDataLine source;
    private ExecutorService executor = null;
    private final ArrayList<byte[]> buffer = new ArrayList<>();
    private FrameBuffer frames = null;
    private Viewer viewer = null;
    private final int aFreq = audioFreq;

    private SystemPlayer(Viewer viewer) {
        this.viewer = viewer;
    }
    
    public void addFrame(Frame frame) {
        BufferedImage fImage = frame.getImage();
        viewer.setImage(fImage);
        int lAL = MasterMixer.getInstance().getAudioLevelLeft();
        int lAR = MasterMixer.getInstance().getAudioLevelRight();
        viewer.setAudioLevel(lAL, lAR);
        viewer.repaint();
        if (source != null) {
            frames.push(frame);
        }
    }

    public void play() throws LineUnavailableException {
        frames = new FrameBuffer(MasterMixer.getInstance().getWidth(), MasterMixer.getInstance().getHeight(), MasterMixer.getInstance().getRate());
// Path: src/webcamstudio/WebcamStudio.java
// public static int audioFreq = 22050;
// 
// Path: src/webcamstudio/components/Viewer.java
// public class Viewer extends javax.swing.JPanel {
//     GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment();
//     GraphicsDevice device = env.getDefaultScreenDevice();
//     GraphicsConfiguration config = device.getDefaultConfiguration();
//     private BufferedImage img = config.createCompatibleImage(320, 240, BufferedImage.TYPE_INT_ARGB);
//     private int audioLeft = 0;
//     private int audioRight=0;
// 
//     /** Creates new form Viewer */
//     public Viewer() {
//         initComponents();
//     }
// 
//     public void setImage(BufferedImage image) {
//         
//         img=image;
//         
//     }
//          
//     public void setAudioLevel(int l, int r){
//         audioLeft = l;
//         audioRight = r;
//     }
//     @Override
//     public void paintComponent(Graphics g) {
//         Graphics2D graph = (Graphics2D) g;
//         
//         graph.setRenderingHint(java.awt.RenderingHints.KEY_INTERPOLATION, 
//                                java.awt.RenderingHints.VALUE_INTERPOLATION_BILINEAR);
//         graph.setRenderingHint(java.awt.RenderingHints.KEY_RENDERING,
//                                java.awt.RenderingHints.VALUE_RENDER_SPEED);
//         graph.setRenderingHint(java.awt.RenderingHints.KEY_ANTIALIASING,
//                                java.awt.RenderingHints.VALUE_ANTIALIAS_OFF);
//         graph.setRenderingHint(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING,
//                                java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
//         graph.setRenderingHint(java.awt.RenderingHints.KEY_FRACTIONALMETRICS,
//                                java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
//         graph.setRenderingHint(java.awt.RenderingHints.KEY_COLOR_RENDERING,
//                                java.awt.RenderingHints.VALUE_COLOR_RENDER_SPEED);
//         graph.setRenderingHint(java.awt.RenderingHints.KEY_DITHERING,
//                                java.awt.RenderingHints.VALUE_DITHER_DISABLE);
// 
//         int w = this.getWidth();
//         int h = this.getHeight();
//         graph.setBackground(Color.BLACK);
//         graph.clearRect(0, 0, w, h);
//         if (img != null) {
//             int imgWidth = h * img.getWidth() / img.getHeight();
//             int border = (w - imgWidth) / 2;
//             graph.drawImage(img, border, 0, imgWidth, h, null);
//         } else {
//             graph.setColor(Color.WHITE);
//             graph.drawString("No Image",10,10);
//         }
//         if (audioLeft > 0 || audioRight > 0){
//             graph.setColor(Color.green);
//             graph.fillRect(0, h - audioLeft * h / 128, 10, audioLeft * h / 128);
//             graph.fillRect(w-10, h - audioRight * h / 128, 10, audioRight * h / 128);
//         }
//     }
// 
//     /** This method is called from within the constructor to
//      * initialize the form.
//      * WARNING: Do NOT modify this code. The content of this method is
//      * always regenerated by the Form Editor.
//      */
//     @SuppressWarnings("unchecked")
//     // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
//     private void initComponents() {
// 
//         setPreferredSize(new java.awt.Dimension(30, 29));
// 
//         javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
//         this.setLayout(layout);
//         layout.setHorizontalGroup(
//             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
//             .addGap(0, 41, Short.MAX_VALUE)
//         );
//         layout.setVerticalGroup(
//             layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
//             .addGap(0, 39, Short.MAX_VALUE)
//         );
//     }// </editor-fold>//GEN-END:initComponents
//     // Variables declaration - do not modify//GEN-BEGIN:variables
//     // End of variables declaration//GEN-END:variables
// }


// Path: src/webcamstudio/mixers/SystemPlayer.java
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import static java.util.concurrent.Executors.newCachedThreadPool;
import javax.sound.sampled.AudioFormat;
import static javax.sound.sampled.AudioSystem.getSourceDataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import static webcamstudio.WebcamStudio.audioFreq;
import webcamstudio.components.Viewer;
import static webcamstudio.util.Tools.sleep;

        return instance;
    }
    
    boolean stopMe = false;
    public boolean stopMePub = stopMe;
    private SourceDataLine source;
    private ExecutorService executor = null;
    private final ArrayList<byte[]> buffer = new ArrayList<>();
    private FrameBuffer frames = null;
    private Viewer viewer = null;
    private final int aFreq = audioFreq;

    private SystemPlayer(Viewer viewer) {
        this.viewer = viewer;
    }
    
    public void addFrame(Frame frame) {
        BufferedImage fImage = frame.getImage();
        viewer.setImage(fImage);
        int lAL = MasterMixer.getInstance().getAudioLevelLeft();
        int lAR = MasterMixer.getInstance().getAudioLevelRight();
        viewer.setAudioLevel(lAL, lAR);
        viewer.repaint();
        if (source != null) {
            frames.push(frame);
        }
    }

    public void play() throws LineUnavailableException {
        frames = new FrameBuffer(MasterMixer.getInstance().getWidth(), MasterMixer.getInstance().getHeight(), MasterMixer.getInstance().getRate());
        AudioFormat format = new AudioFormat(audioFreq, 16, 2, true, true);