// Path: app/src/main/java/tech/schober/vinylcast/audio/AudioRecordStreamProvider.java
// public class AudioRecordStreamProvider implements AudioStreamProvider {
// 
//     private static final String TAG = "AudioRecorder";
// 
//     @Retention(RetentionPolicy.SOURCE)
//     @IntDef({AUDIO_API_OPENSLES, AUDIO_API_AAUDIO})
//     public @interface AudioApi {}
//     public static final int AUDIO_API_OPENSLES = 1;
//     public static final int AUDIO_API_AAUDIO = 2;
// 
//     public static final int AUDIO_DEVICE_ID_NONE = -1;
//     public static final int AUDIO_DEVICE_ID_AUTO_SELECT = 0;
// 
//     protected int bufferSize;
//     private CopyOnWriteArrayList<OutputStream> nativeAudioWriteStreams = new CopyOnWriteArrayList<>();
// 
//     public AudioRecordStreamProvider(int recordingDeviceId, int playbackDeviceId, boolean lowLatency, int bufferSize) {
//         NativeAudioEngine.setRecordingDeviceId(recordingDeviceId);
//         NativeAudioEngine.setPlaybackDeviceId(playbackDeviceId);
//         NativeAudioEngine.setLowLatency(lowLatency);
//         this.bufferSize = bufferSize;
//     }
// 
//     public boolean start() {
//         Log.d(TAG, "start");
// 
//         boolean preparedSuccess = NativeAudioEngine.prepareRecording();
//         if (!preparedSuccess) {
//             Log.w(TAG, "Failed to Prepare to Record.");
//             return false;
//         }
//         Log.d(TAG, "Prepared to Record - sampleRate: " + NativeAudioEngine.getSampleRate() +", channel count: " + NativeAudioEngine.getChannelCount());
// 
//         // callback from NativeAudioEngine with audioData will end up on own thread
//         NativeAudioEngine.setAudioDataListener(new NativeAudioEngineListener() {
//             @Override
//             public void onAudioData(byte[] audioData) {
//                 //Log.v(TAG, "audioData.length: " + audioData.length);
//                 for (OutputStream writeStream : nativeAudioWriteStreams) {
//                     try {
//                         writeStream.write(audioData);
//                         writeStream.flush();
//                     } catch (IOException e) {
//                         Log.w(TAG, "Exception writing to raw audio output stream. Removing from list of streams.", e);
//                         nativeAudioWriteStreams.remove(writeStream);
//                     }
//                 }
// 
//                 if (nativeAudioWriteStreams.isEmpty()) {
//                     Log.e(TAG, "No open write streams.");
//                 }
//             }
//         });
// 
//         return NativeAudioEngine.startRecording();
//     }
// 
//     public boolean stop() {
//         Log.d(TAG, "stop");
// 
//         try {
//             for (OutputStream writeStream : nativeAudioWriteStreams) {
//                 nativeAudioWriteStreams.remove(writeStream);
//                 writeStream.close();
//             }
//         } catch (IOException e) {
//             Log.e(TAG, "Exception closing streams", e);
//         }
// 
//         return NativeAudioEngine.stopRecording();
//     }
// 
//     @Override
//     public InputStream getAudioInputStream() {
//         Log.d(TAG, "getAudioInputStream");
//         Pair<OutputStream, InputStream> audioStreams;
//         try {
//             audioStreams = VinylCastHelpers.getPipedAudioStreams(bufferSize);
//         } catch (IOException e) {
//             Log.e(TAG, "Exception creating audio stream", e);
//             return null;
//         }
//         nativeAudioWriteStreams.add(audioStreams.first);
//         return audioStreams.second;
//     }
// 
//     @Override
//     public int getSampleRate() {
//         return NativeAudioEngine.getSampleRate();
//     }
// 
//     @Override
//     public int getChannelCount() {
//         return NativeAudioEngine.getChannelCount();
//     }
// 
//     @Override
//     public int getAudioEncoding() {
//         return AUDIO_ENCODING_WAV;
//     }
// 
//     public String getAudioApi() {
//         switch(NativeAudioEngine.getAudioApi()) {
//             case AUDIO_API_OPENSLES:
//                 return "OpenSL ES";
//             case AUDIO_API_AAUDIO:
//                 return "AAudio";
//             default:
//                 return "[not recording]";
//         }
//     }
// 
//     public static int getAudioRecordStreamSampleRate() {
//         return NativeAudioEngine.getSampleRate();
//     }
// 
//     public static int getAudioRecordStreamChannelCount() {
//         return NativeAudioEngine.getChannelCount();
//     }
// 
//     public static int getAudioRecordStreamBitRate() {
//         return NativeAudioEngine.getBitRate();
//     }
// 
//     public static @AudioEncoding int getAudioRecordStreamAudioEncoding() {
//         return AUDIO_ENCODING_WAV;
//     }
// }


import android.annotation.TargetApi;
import android.content.Context;
import android.media.AudioDeviceCallback;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Spinner;
import androidx.preference.ListPreference;
import androidx.preference.PreferenceViewHolder;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import tech.schober.vinylcast.R;
import tech.schober.vinylcast.audio.AudioRecordStreamProvider;
        }
    }

    @Override
    public void onBindViewHolder(PreferenceViewHolder view) {
        mSpinner = view.itemView.findViewById(R.id.spinner);
        mSpinner.setAdapter(mDeviceAdapter);
        mSpinner.setOnItemSelectedListener(mItemSelectedListener);
        mSpinner.setSelection(findSpinnerIndexOfValue(getValue()));
        super.onBindViewHolder(view);
    }

    private int findSpinnerIndexOfValue(String value) {
        CharSequence[] entryValues = getEntryValues();
        if (value != null && entryValues != null) {
            for (int i = entryValues.length - 1; i >= 0; i--) {
                if (entryValues[i].equals(value)) {
                    return i;
                }
            }
        }
        return Spinner.INVALID_POSITION;
    }

    @TargetApi(23)
    public void setDirectionType(int directionType){
        this.mDirectionType = directionType;

        if (directionType == AudioManager.GET_DEVICES_OUTPUTS) {
            // Add an entry for NONE to the list
// Path: app/src/main/java/tech/schober/vinylcast/audio/AudioRecordStreamProvider.java
// public class AudioRecordStreamProvider implements AudioStreamProvider {
// 
//     private static final String TAG = "AudioRecorder";
// 
//     @Retention(RetentionPolicy.SOURCE)
//     @IntDef({AUDIO_API_OPENSLES, AUDIO_API_AAUDIO})
//     public @interface AudioApi {}
//     public static final int AUDIO_API_OPENSLES = 1;
//     public static final int AUDIO_API_AAUDIO = 2;
// 
//     public static final int AUDIO_DEVICE_ID_NONE = -1;
//     public static final int AUDIO_DEVICE_ID_AUTO_SELECT = 0;
// 
//     protected int bufferSize;
//     private CopyOnWriteArrayList<OutputStream> nativeAudioWriteStreams = new CopyOnWriteArrayList<>();
// 
//     public AudioRecordStreamProvider(int recordingDeviceId, int playbackDeviceId, boolean lowLatency, int bufferSize) {
//         NativeAudioEngine.setRecordingDeviceId(recordingDeviceId);
//         NativeAudioEngine.setPlaybackDeviceId(playbackDeviceId);
//         NativeAudioEngine.setLowLatency(lowLatency);
//         this.bufferSize = bufferSize;
//     }
// 
//     public boolean start() {
//         Log.d(TAG, "start");
// 
//         boolean preparedSuccess = NativeAudioEngine.prepareRecording();
//         if (!preparedSuccess) {
//             Log.w(TAG, "Failed to Prepare to Record.");
//             return false;
//         }
//         Log.d(TAG, "Prepared to Record - sampleRate: " + NativeAudioEngine.getSampleRate() +", channel count: " + NativeAudioEngine.getChannelCount());
// 
//         // callback from NativeAudioEngine with audioData will end up on own thread
//         NativeAudioEngine.setAudioDataListener(new NativeAudioEngineListener() {
//             @Override
//             public void onAudioData(byte[] audioData) {
//                 //Log.v(TAG, "audioData.length: " + audioData.length);
//                 for (OutputStream writeStream : nativeAudioWriteStreams) {
//                     try {
//                         writeStream.write(audioData);
//                         writeStream.flush();
//                     } catch (IOException e) {
//                         Log.w(TAG, "Exception writing to raw audio output stream. Removing from list of streams.", e);
//                         nativeAudioWriteStreams.remove(writeStream);
//                     }
//                 }
// 
//                 if (nativeAudioWriteStreams.isEmpty()) {
//                     Log.e(TAG, "No open write streams.");
//                 }
//             }
//         });
// 
//         return NativeAudioEngine.startRecording();
//     }
// 
//     public boolean stop() {
//         Log.d(TAG, "stop");
// 
//         try {
//             for (OutputStream writeStream : nativeAudioWriteStreams) {
//                 nativeAudioWriteStreams.remove(writeStream);
//                 writeStream.close();
//             }
//         } catch (IOException e) {
//             Log.e(TAG, "Exception closing streams", e);
//         }
// 
//         return NativeAudioEngine.stopRecording();
//     }
// 
//     @Override
//     public InputStream getAudioInputStream() {
//         Log.d(TAG, "getAudioInputStream");
//         Pair<OutputStream, InputStream> audioStreams;
//         try {
//             audioStreams = VinylCastHelpers.getPipedAudioStreams(bufferSize);
//         } catch (IOException e) {
//             Log.e(TAG, "Exception creating audio stream", e);
//             return null;
//         }
//         nativeAudioWriteStreams.add(audioStreams.first);
//         return audioStreams.second;
//     }
// 
//     @Override
//     public int getSampleRate() {
//         return NativeAudioEngine.getSampleRate();
//     }
// 
//     @Override
//     public int getChannelCount() {
//         return NativeAudioEngine.getChannelCount();
//     }
// 
//     @Override
//     public int getAudioEncoding() {
//         return AUDIO_ENCODING_WAV;
//     }
// 
//     public String getAudioApi() {
//         switch(NativeAudioEngine.getAudioApi()) {
//             case AUDIO_API_OPENSLES:
//                 return "OpenSL ES";
//             case AUDIO_API_AAUDIO:
//                 return "AAudio";
//             default:
//                 return "[not recording]";
//         }
//     }
// 
//     public static int getAudioRecordStreamSampleRate() {
//         return NativeAudioEngine.getSampleRate();
//     }
// 
//     public static int getAudioRecordStreamChannelCount() {
//         return NativeAudioEngine.getChannelCount();
//     }
// 
//     public static int getAudioRecordStreamBitRate() {
//         return NativeAudioEngine.getBitRate();
//     }
// 
//     public static @AudioEncoding int getAudioRecordStreamAudioEncoding() {
//         return AUDIO_ENCODING_WAV;
//     }
// }


// Path: app/src/main/java/com/google/sample/audio_device/AudioDevicePreference.java
import android.annotation.TargetApi;
import android.content.Context;
import android.media.AudioDeviceCallback;
import android.media.AudioDeviceInfo;
import android.media.AudioManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Spinner;
import androidx.preference.ListPreference;
import androidx.preference.PreferenceViewHolder;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import tech.schober.vinylcast.R;
import tech.schober.vinylcast.audio.AudioRecordStreamProvider;

        }
    }

    @Override
    public void onBindViewHolder(PreferenceViewHolder view) {
        mSpinner = view.itemView.findViewById(R.id.spinner);
        mSpinner.setAdapter(mDeviceAdapter);
        mSpinner.setOnItemSelectedListener(mItemSelectedListener);
        mSpinner.setSelection(findSpinnerIndexOfValue(getValue()));
        super.onBindViewHolder(view);
    }

    private int findSpinnerIndexOfValue(String value) {
        CharSequence[] entryValues = getEntryValues();
        if (value != null && entryValues != null) {
            for (int i = entryValues.length - 1; i >= 0; i--) {
                if (entryValues[i].equals(value)) {
                    return i;
                }
            }
        }
        return Spinner.INVALID_POSITION;
    }

    @TargetApi(23)
    public void setDirectionType(int directionType){
        this.mDirectionType = directionType;

        if (directionType == AudioManager.GET_DEVICES_OUTPUTS) {
            // Add an entry for NONE to the list
            mDeviceAdapter.insert(new AudioDeviceListEntry(AudioRecordStreamProvider.AUDIO_DEVICE_ID_NONE, AudioDeviceInfo.TYPE_UNKNOWN,