1 /* 2 * Copyright (C) 2015 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.example.android.midiscope; 18 19 import android.app.ActionBar; 20 import android.app.Activity; 21 import android.media.midi.MidiDeviceInfo; 22 import android.media.midi.MidiManager; 23 import android.media.midi.MidiReceiver; 24 import android.os.Bundle; 25 import android.view.Menu; 26 import android.view.MenuItem; 27 import android.view.View; 28 import android.view.WindowManager; 29 import android.widget.ScrollView; 30 import android.widget.TextView; 31 import android.widget.Toolbar; 32 33 import com.example.android.common.midi.MidiFramer; 34 import com.example.android.common.midi.MidiOutputPortSelector; 35 import com.example.android.common.midi.MidiPortWrapper; 36 37 import java.util.LinkedList; 38 39 /** 40 * App that provides a MIDI echo service. 41 */ 42 public class MainActivity extends Activity implements ScopeLogger { 43 44 private static final int MAX_LINES = 100; 45 46 private final LinkedList<String> mLogLines = new LinkedList<>(); 47 private TextView mLog; 48 private ScrollView mScroller; 49 private MidiOutputPortSelector mLogSenderSelector; 50 51 @Override onCreate(Bundle savedInstanceState)52 public void onCreate(Bundle savedInstanceState) { 53 super.onCreate(savedInstanceState); 54 setContentView(R.layout.main); 55 56 setActionBar((Toolbar) findViewById(R.id.toolbar)); 57 ActionBar actionBar = getActionBar(); 58 if (actionBar != null) { 59 actionBar.setDisplayShowTitleEnabled(false); 60 } 61 62 mLog = (TextView) findViewById(R.id.log); 63 mScroller = (ScrollView) findViewById(R.id.scroll); 64 65 // Setup MIDI 66 MidiManager midiManager = (MidiManager) getSystemService(MIDI_SERVICE); 67 68 // Receiver that prints the messages. 69 MidiReceiver loggingReceiver = new LoggingReceiver(this); 70 71 // Receiver that parses raw data into complete messages. 72 MidiFramer connectFramer = new MidiFramer(loggingReceiver); 73 74 // Setup a menu to select an input source. 75 mLogSenderSelector = new MidiOutputPortSelector(midiManager, this, R.id.spinner_senders) { 76 @Override 77 public void onPortSelected(final MidiPortWrapper wrapper) { 78 super.onPortSelected(wrapper); 79 if (wrapper != null) { 80 mLogLines.clear(); 81 MidiDeviceInfo deviceInfo = wrapper.getDeviceInfo(); 82 if (deviceInfo == null) { 83 log(getString(R.string.header_text)); 84 } else { 85 log(MidiPrinter.formatDeviceInfo(deviceInfo)); 86 } 87 } 88 } 89 }; 90 mLogSenderSelector.getSender().connect(connectFramer); 91 92 // Tell the virtual device to log its messages here.. 93 MidiScope.setScopeLogger(this); 94 } 95 96 @Override onDestroy()97 public void onDestroy() { 98 mLogSenderSelector.onClose(); 99 // The scope will live on as a service so we need to tell it to stop 100 // writing log messages to this Activity. 101 MidiScope.setScopeLogger(null); 102 super.onDestroy(); 103 } 104 105 @Override onCreateOptionsMenu(Menu menu)106 public boolean onCreateOptionsMenu(Menu menu) { 107 getMenuInflater().inflate(R.menu.main, menu); 108 setKeepScreenOn(menu.findItem(R.id.action_keep_screen_on).isChecked()); 109 return true; 110 } 111 112 @Override onOptionsItemSelected(MenuItem item)113 public boolean onOptionsItemSelected(MenuItem item) { 114 switch (item.getItemId()) { 115 case R.id.action_clear_all: 116 mLogLines.clear(); 117 logOnUiThread(""); 118 break; 119 case R.id.action_keep_screen_on: 120 boolean checked = !item.isChecked(); 121 setKeepScreenOn(checked); 122 item.setChecked(checked); 123 break; 124 } 125 return super.onOptionsItemSelected(item); 126 } 127 setKeepScreenOn(boolean keepScreenOn)128 private void setKeepScreenOn(boolean keepScreenOn) { 129 if (keepScreenOn) { 130 getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 131 } else { 132 getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 133 } 134 } 135 136 @Override log(final String string)137 public void log(final String string) { 138 runOnUiThread(new Runnable() { 139 @Override 140 public void run() { 141 logOnUiThread(string); 142 } 143 }); 144 } 145 146 /** 147 * Logs a message to our TextView. This needs to be called from the UI thread. 148 */ logOnUiThread(String s)149 private void logOnUiThread(String s) { 150 mLogLines.add(s); 151 if (mLogLines.size() > MAX_LINES) { 152 mLogLines.removeFirst(); 153 } 154 // Render line buffer to one String. 155 StringBuilder sb = new StringBuilder(); 156 for (String line : mLogLines) { 157 sb.append(line).append('\n'); 158 } 159 mLog.setText(sb.toString()); 160 mScroller.fullScroll(View.FOCUS_DOWN); 161 } 162 } 163