• 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 mAAudioRecommended = 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                     setSpinnersEnabled(true);
113                 }
114             }
115         });
116         findViewById(R.id.slesButton).setOnClickListener(new RadioButton.OnClickListener(){
117             @Override
118             public void onClick(View v) {
119                 if (((RadioButton)v).isChecked()) {
120                     apiSelection = OBOE_API_OPENSL_ES;
121                     setSpinnersEnabled(false);
122                 }
123             }
124         });
125 
126         LiveEffectEngine.setDefaultStreamValues(this);
127     }
128 
EnableAudioApiUI(boolean enable)129     private void EnableAudioApiUI(boolean enable) {
130         if(apiSelection == OBOE_API_AAUDIO && !mAAudioRecommended)
131         {
132             apiSelection = OBOE_API_OPENSL_ES;
133         }
134         findViewById(R.id.slesButton).setEnabled(enable);
135         if(!mAAudioRecommended) {
136             findViewById(R.id.aaudioButton).setEnabled(false);
137         } else {
138             findViewById(R.id.aaudioButton).setEnabled(enable);
139         }
140 
141         ((RadioGroup)findViewById(R.id.apiSelectionGroup))
142           .check(apiSelection == OBOE_API_AAUDIO ? R.id.aaudioButton : R.id.slesButton);
143         setSpinnersEnabled(enable);
144     }
145 
146     @Override
onStart()147     protected void onStart() {
148         super.onStart();
149         setVolumeControlStream(AudioManager.STREAM_MUSIC);
150     }
151 
152     @Override
onResume()153     protected void onResume() {
154         super.onResume();
155         LiveEffectEngine.create();
156         mAAudioRecommended = LiveEffectEngine.isAAudioRecommended();
157         EnableAudioApiUI(true);
158         LiveEffectEngine.setAPI(apiSelection);
159     }
160     @Override
onPause()161     protected void onPause() {
162         stopEffect();
163         LiveEffectEngine.delete();
164         super.onPause();
165     }
166 
toggleEffect()167     public void toggleEffect() {
168         if (isPlaying) {
169             stopEffect();
170         } else {
171             LiveEffectEngine.setAPI(apiSelection);
172             startEffect();
173         }
174     }
175 
startEffect()176     private void startEffect() {
177         Log.d(TAG, "Attempting to start");
178 
179         if (!isRecordPermissionGranted()){
180             requestRecordPermission();
181             return;
182         }
183 
184         boolean success = LiveEffectEngine.setEffectOn(true);
185         if (success) {
186             statusText.setText(R.string.status_playing);
187             toggleEffectButton.setText(R.string.stop_effect);
188             isPlaying = true;
189             EnableAudioApiUI(false);
190         } else {
191             statusText.setText(R.string.status_open_failed);
192             isPlaying = false;
193         }
194     }
195 
stopEffect()196     private void stopEffect() {
197         Log.d(TAG, "Playing, attempting to stop");
198         LiveEffectEngine.setEffectOn(false);
199         resetStatusView();
200         toggleEffectButton.setText(R.string.start_effect);
201         isPlaying = false;
202         EnableAudioApiUI(true);
203     }
204 
setSpinnersEnabled(boolean isEnabled)205     private void setSpinnersEnabled(boolean isEnabled){
206         if (((RadioButton)findViewById(R.id.slesButton)).isChecked())
207         {
208             isEnabled = false;
209             playbackDeviceSpinner.setSelection(0);
210             recordingDeviceSpinner.setSelection(0);
211         }
212         recordingDeviceSpinner.setEnabled(isEnabled);
213         playbackDeviceSpinner.setEnabled(isEnabled);
214     }
215 
getRecordingDeviceId()216     private int getRecordingDeviceId(){
217         return ((AudioDeviceListEntry)recordingDeviceSpinner.getSelectedItem()).getId();
218     }
219 
getPlaybackDeviceId()220     private int getPlaybackDeviceId(){
221         return ((AudioDeviceListEntry)playbackDeviceSpinner.getSelectedItem()).getId();
222     }
223 
isRecordPermissionGranted()224     private boolean isRecordPermissionGranted() {
225         return (ActivityCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) ==
226                 PackageManager.PERMISSION_GRANTED);
227     }
228 
requestRecordPermission()229     private void requestRecordPermission(){
230         ActivityCompat.requestPermissions(
231                 this,
232                 new String[]{Manifest.permission.RECORD_AUDIO},
233                 AUDIO_EFFECT_REQUEST);
234     }
235 
resetStatusView()236     private void resetStatusView() {
237         statusText.setText(R.string.status_warning);
238     }
239 
240     @Override
onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)241     public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
242                                            @NonNull int[] grantResults) {
243 
244         if (AUDIO_EFFECT_REQUEST != requestCode) {
245             super.onRequestPermissionsResult(requestCode, permissions, grantResults);
246             return;
247         }
248 
249         if (grantResults.length != 1 ||
250                 grantResults[0] != PackageManager.PERMISSION_GRANTED) {
251 
252             // User denied the permission, without this we cannot record audio
253             // Show a toast and update the status accordingly
254             statusText.setText(R.string.status_record_audio_denied);
255             Toast.makeText(getApplicationContext(),
256                     getString(R.string.need_record_audio_permission),
257                     Toast.LENGTH_SHORT)
258                     .show();
259         } else {
260             // Permission was granted, start live effect
261             toggleEffect();
262         }
263     }
264 }
265