/*
 * BRLTTY - A background process providing access to the console screen (when in
 *          text mode) for a blind person using a refreshable braille display.
 *
 * Copyright (C) 1995-2013 by The BRLTTY Developers.
 *
 * BRLTTY comes with ABSOLUTELY NO WARRANTY.
 *
 * This is free software, placed under the terms of the
 * GNU General Public License, as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any
 * later version. Please see the file LICENSE-GPL for details.
 *
 * Web Page: http://mielke.cc/brltty/
 *
 * This software is maintained by Dave Mielke <dave@mielke.cc>.
 */

package org.a11y.brltty.android;

import android.util.Log;

import android.media.AudioManager;
import android.media.AudioFormat;
import android.media.AudioTrack;

public final class PcmDevice {
  private static final String LOG_TAG = PcmDevice.class.getName();

  private static final int streamType = AudioManager.STREAM_NOTIFICATION;
  private static final int trackMode = AudioTrack.MODE_STREAM;
  private static final int audioFormat = AudioFormat.ENCODING_PCM_16BIT;

  private int sampleRate = 8000;
  private int channelConfiguration = AudioFormat.CHANNEL_OUT_MONO;
  private AudioTrack audioTrack = null;

  public int getSampleRate () {
    return sampleRate;
  }

  public void setSampleRate (int rate) {
    sampleRate = rate;
  }

  public int getChannelConfiguration () {
    return channelConfiguration;
  }

  public int getChannelCount () {
    switch (getChannelConfiguration()) {
      default:
      case AudioFormat.CHANNEL_OUT_MONO:
        return 1;

      case AudioFormat.CHANNEL_OUT_STEREO:
        return 2;
    }
  }

  public void setChannelCount (int count) {
    switch (count) {
      default:
      case 1:
        channelConfiguration = AudioFormat.CHANNEL_OUT_MONO;
        break;

      case 2:
        channelConfiguration = AudioFormat.CHANNEL_OUT_STEREO;
        break;
    }
  }

  public int getBufferSize () {
    return AudioTrack.getMinBufferSize(getSampleRate(), getChannelConfiguration(), audioFormat);
  }

  private AudioTrack newAudioTrack () {
    return new AudioTrack(streamType, getSampleRate(), getChannelConfiguration(),
                          audioFormat, getBufferSize(), trackMode);
  }

  public boolean write (short[] samples) {
    if (audioTrack == null) audioTrack = newAudioTrack();

    int offset = 0;
    int length = samples.length;

    while (length > 0) {
      int result = audioTrack.write(samples, offset, length);
      if (result < 1) return false;

      audioTrack.play();
      offset += result;
      length -= result;
    }

    return true;
  }

  public void cancel () {
    audioTrack.pause();
    audioTrack.flush();
  }

  public void close () {
    cancel();
    audioTrack.release();
    audioTrack = null;
  }

  public PcmDevice () {
  }
}

@@ -1246,16 +1246,84 @@
  null;%0A%0A
+  public boolean isStarted () %7B%0A    return audioTrack != null;%0A  %7D%0A%0A
   public
@@ -1418,16 +1418,34 @@
 e) %7B%0A   
+ if (!isStarted())
  sampleR
@@ -1803,24 +1803,50 @@
 nt count) %7B%0A
+    if (!isStarted()) %7B%0A  
     switch (
@@ -1850,24 +1850,26 @@
 h (count) %7B%0A
+  
       defaul
@@ -1881,16 +1881,18 @@
     
+  
 case 1:%0A
     
@@ -1887,16 +1887,18 @@
 case 1:%0A
+  
         
@@ -1962,16 +1962,18 @@
     
+  
 break;%0A%0A
     
@@ -1968,16 +1968,18 @@
 break;%0A%0A
+  
       ca
@@ -1984,32 +1984,34 @@
 case 2:%0A        
+  
 channelConfigura
@@ -2057,23 +2057,33 @@
         
+  
 break;%0A
+      %7D%0A
     %7D%0A  
@@ -2421,56 +2421,55 @@
 %0A  p
-ublic boolean write (short%5B%5D samples) %7B%0A    if (
+rotected void start () %7B%0A    if (!isStarted()) 
 audi
@@ -2480,17 +2480,13 @@
 ck =
-=
  n
-ull) a
+ewA
 udio
@@ -2490,32 +2490,77 @@
 dioTrack
- = newAudioTrack
+();%0A  %7D%0A%0A  public boolean write (short%5B%5D samples) %7B%0A    start
 ();%0A%0A   

Add a bit more logic to Android PCM support. (dm)