• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.google.oboe.samples.liveEffect;
18 
19 import android.Manifest;
20 import android.app.Activity;
21 import android.content.pm.PackageManager;
22 import android.media.AudioManager;
23 import android.os.Build;
24 import android.os.Bundle;
25 import androidx.annotation.NonNull;
26 import androidx.core.app.ActivityCompat;
27 import android.util.Log;
28 import android.view.View;
29 import android.widget.AdapterView;
30 import android.widget.Button;
31 import android.widget.RadioButton;
32 import android.widget.RadioGroup;
33 import android.widget.TextView;
34 import android.widget.Toast;
35 
36 import com.google.oboe.samples.audio_device.AudioDeviceListEntry;
37 import com.google.oboe.samples.audio_device.AudioDeviceSpinner;
38 
39 /**
40  * TODO: Update README.md and go through and comment sample
41  */
42 public class MainActivity extends Activity
43         implements ActivityCompat.OnRequestPermissionsResultCallback {
44 
45     private static final String TAG = MainActivity.class.getName();
46     private static final int AUDIO_EFFECT_REQUEST = 0;
47     private static final int OBOE_API_AAUDIO = 0;
48     private static final int OBOE_API_OPENSL_ES=1;
49 
50     private TextView statusText;
51     private Button toggleEffectButton;
52     private AudioDeviceSpinner recordingDeviceSpinner;
53     private AudioDeviceSpinner playbackDeviceSpinner;
54     private boolean isPlaying = false;
55 
56     private int apiSelection = OBOE_API_AAUDIO;
57     private boolean aaudioSupported = true;
58 
59     @Override
onCreate(Bundle savedInstanceState)60     protected void onCreate(Bundle savedInstanceState) {
61         super.onCreate(savedInstanceState);
62         setContentView(R.layout.activity_main);
63 
64         statusText = findViewById(R.id.status_view_text);
65         toggleEffectButton = findViewById(R.id.button_toggle_effect);
66         toggleEffectButton.setOnClickListener(new View.OnClickListener() {
67             @Override
68             public void onClick(View view) {
69                 toggleEffect();
70             }
71         });
72         toggleEffectButton.setText(getString(R.string.start_effect));
73 
74         recordingDeviceSpinner = findViewById(R.id.recording_devices_spinner);
75         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
76             recordingDeviceSpinner.setDirectionType(AudioManager.GET_DEVICES_INPUTS);
77             recordingDeviceSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
78                 @Override
79                 public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
80                     LiveEffectEngine.setRecordingDeviceId(getRecordingDeviceId());
81                 }
82 
83                 @Override
84                 public void onNothingSelected(AdapterView<?> adapterView) {
85                     // Do nothing
86                 }
87             });
88         }
89 
90         playbackDeviceSpinner = findViewById(R.id.playback_devices_spinner);
91         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
92             playbackDeviceSpinner.setDirectionType(AudioManager.GET_DEVICES_OUTPUTS);
93             playbackDeviceSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
94                 @Override
95                 public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
96                     LiveEffectEngine.setPlaybackDeviceId(getPlaybackDeviceId());
97                 }
98 
99                 @Override
100                 public void onNothingSelected(AdapterView<?> adapterView) {
101                     // Do nothing
102                 }
103             });
104         }
105 
106         ((RadioGroup)findViewById(R.id.apiSelectionGroup)).check(R.id.aaudioButton);
107         findViewById(R.id.aaudioButton).setOnClickListener(new RadioButton.OnClickListener(){
108             @Override
109             public void onClick(View v) {
110                 if (((RadioButton)v).isChecked()) {
111                     apiSelection = OBOE_API_AAUDIO;
112                 }
113             }
114         });
115         findViewById(R.id.slesButton).setOnClickListener(new RadioButton.OnClickListener(){
116             @Override
117             public void onClick(View v) {
118                 if (((RadioButton)v).isChecked()) {
119                     apiSelection = OBOE_API_OPENSL_ES;
120                 }
121             }
122         });
123 
124         LiveEffectEngine.setDefaultStreamValues(this);
125     }
126 
EnableAudioApiUI(boolean enable)127     private void EnableAudioApiUI(boolean enable) {
128         if(apiSelection == OBOE_API_AAUDIO && !aaudioSupported)
129         {
130             apiSelection = OBOE_API_OPENSL_ES;
131         }
132         findViewById(R.id.slesButton).setEnabled(enable);
133         if(!aaudioSupported) {
134             findViewById(R.id.aaudioButton).setEnabled(false);
135         } else {
136             findViewById(R.id.aaudioButton).setEnabled(enable);
137         }
138 
139         ((RadioGroup)findViewById(R.id.apiSelectionGroup))
140           .check(apiSelection == OBOE_API_AAUDIO ? R.id.aaudioButton : R.id.slesButton);
141     }
142 
143     @Override
onStart()144     protected void onStart() {
145         super.onStart();
146         setVolumeControlStream(AudioManager.STREAM_MUSIC);
147     }
148 
149     @Override
onResume()150     protected void onResume() {
151         super.onResume();
152         LiveEffectEngine.create();
153         aaudioSupported = LiveEffectEngine.isAAudioSupported();
154         EnableAudioApiUI(true);
155         LiveEffectEngine.setAPI(apiSelection);
156     }
157     @Override
onPause()158     protected void onPause() {
159         stopEffect();
160         LiveEffectEngine.delete();
161         super.onPause();
162     }
163 
toggleEffect()164     public void toggleEffect() {
165         if (isPlaying) {
166             stopEffect();
167         } else {
168             LiveEffectEngine.setAPI(apiSelection);
169             startEffect();
170         }
171     }
172 
startEffect()173     private void startEffect() {
174         Log.d(TAG, "Attempting to start");
175 
176         if (!isRecordPermissionGranted()){
177             requestRecordPermission();
178             return;
179         }
180 
181         boolean success = LiveEffectEngine.setEffectOn(true);
182         if (success) {
183             setSpinnersEnabled(false);
184             statusText.setText(R.string.status_playing);
185             toggleEffectButton.setText(R.string.stop_effect);
186             isPlaying = true;
187             EnableAudioApiUI(false);
188         } else {
189             statusText.setText(R.string.status_open_failed);
190             isPlaying = false;
191         }
192     }
193 
stopEffect()194     private void stopEffect() {
195         Log.d(TAG, "Playing, attempting to stop");
196         LiveEffectEngine.setEffectOn(false);
197         resetStatusView();
198         toggleEffectButton.setText(R.string.start_effect);
199         isPlaying = false;
200         setSpinnersEnabled(true);
201         EnableAudioApiUI(true);
202     }
203 
setSpinnersEnabled(boolean isEnabled)204     private void setSpinnersEnabled(boolean isEnabled){
205         recordingDeviceSpinner.setEnabled(isEnabled);
206         playbackDeviceSpinner.setEnabled(isEnabled);
207     }
208 
getRecordingDeviceId()209     private int getRecordingDeviceId(){
210         return ((AudioDeviceListEntry)recordingDeviceSpinner.getSelectedItem()).getId();
211     }
212 
getPlaybackDeviceId()213     private int getPlaybackDeviceId(){
214         return ((AudioDeviceListEntry)playbackDeviceSpinner.getSelectedItem()).getId();
215     }
216 
isRecordPermissionGranted()217     private boolean isRecordPermissionGranted() {
218         return (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) ==
219                 PackageManager.PERMISSION_GRANTED);
220     }
221 
requestRecordPermission()222     private void requestRecordPermission(){
223         ActivityCompat.requestPermissions(
224                 this,
225                 new String[]{Manifest.permission.RECORD_AUDIO},
226                 AUDIO_EFFECT_REQUEST);
227     }
228 
resetStatusView()229     private void resetStatusView() {
230         statusText.setText(R.string.status_warning);
231     }
232 
233     @Override
onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)234     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
235                                            @NonNull int[] grantResults) {
236 
237         if (AUDIO_EFFECT_REQUEST != requestCode) {
238             super.onRequestPermissionsResult(requestCode, permissions, grantResults);
239             return;
240         }
241 
242         if (grantResults.length != 1 ||
243                 grantResults[0] != PackageManager.PERMISSION_GRANTED) {
244 
245             // User denied the permission, without this we cannot record audio
246             // Show a toast and update the status accordingly
247             statusText.setText(R.string.status_record_audio_denied);
248             Toast.makeText(getApplicationContext(),
249                     getString(R.string.need_record_audio_permission),
250                     Toast.LENGTH_SHORT)
251                     .show();
252         } else {
253             // Permission was granted, start live effect
254             toggleEffect();
255         }
256     }
257 }
258