now with support for foreground privileges
[pdlib:btmidi.git] / BluetoothMidiDemo / src / com / noisepages / nettoyeur / mididemo / PianoActivity.java
1 /**\r
2  * For information on usage and redistribution, and for a DISCLAIMER OF ALL\r
3  * WARRANTIES, see the file, "LICENSE.txt," in this distribution.\r
4  * \r
5  * Piano GUI based on MyPiano by ZhangFL\r
6  * http://code.google.com/p/mobexamples/wiki/android_mypiano\r
7  * http://www.eoeandroid.com/space.php?uid=1178\r
8  */\r
9 \r
10 package com.noisepages.nettoyeur.mididemo;\r
11 \r
12 import java.io.IOException;\r
13 \r
14 import com.noisepages.nettoyeur.bluetooth.BluetoothSppConnection;\r
15 import com.noisepages.nettoyeur.bluetooth.DeviceListActivity;\r
16 import com.noisepages.nettoyeur.bluetooth.midi.BluetoothMidiReceiver;\r
17 import com.noisepages.nettoyeur.bluetooth.midi.BluetoothMidiService;\r
18 \r
19 import android.app.Activity;\r
20 import android.bluetooth.BluetoothDevice;\r
21 import android.content.ComponentName;\r
22 import android.content.Intent;\r
23 import android.content.ServiceConnection;\r
24 import android.os.Bundle;\r
25 import android.os.IBinder;\r
26 import android.util.Log;\r
27 import android.view.Menu;\r
28 import android.view.MenuInflater;\r
29 import android.view.MenuItem;\r
30 import android.view.MotionEvent;\r
31 import android.view.View;\r
32 import android.widget.ImageButton;\r
33 import android.widget.Toast;\r
34 \r
35 \r
36 public class PianoActivity extends Activity implements View.OnTouchListener {\r
37 \r
38         private static final String TAG = "BluetoothMidiDemo";\r
39         private static final int CONNECT = 1;\r
40         private boolean touchState = false;\r
41         private ImageButton[] keys;\r
42         private final int[] imageUp = new int[] { R.drawable.white1, R.drawable.black1,\r
43                         R.drawable.white2, R.drawable.black2, R.drawable.white3,\r
44                         R.drawable.white4, R.drawable.black3, R.drawable.white5,\r
45                         R.drawable.black4, R.drawable.white6, R.drawable.black5,\r
46                         R.drawable.white7, R.drawable.white8 };\r
47         private final int[] imageDown = new int[] { R.drawable.white11,\r
48                         R.drawable.black11, R.drawable.white21, R.drawable.black21,\r
49                         R.drawable.white31, R.drawable.white41, R.drawable.black31,\r
50                         R.drawable.white51, R.drawable.black41, R.drawable.white61,\r
51                         R.drawable.black51, R.drawable.white71, R.drawable.white81 };\r
52         private BluetoothMidiService midiService = null;\r
53 \r
54         private final BluetoothMidiReceiver receiver = new BluetoothMidiReceiver() {\r
55 \r
56                 @Override\r
57                 public void onDeviceConnected(BluetoothDevice device) {\r
58                         toast("Device connected: " + device);\r
59                 }\r
60 \r
61                 @Override\r
62                 public void onConnectionLost() {\r
63                         toast("MIDI connection lost");\r
64                 }\r
65 \r
66                 @Override\r
67                 public void onConnectionFailed() {\r
68                         toast("MIDI connection failed");\r
69                 }\r
70 \r
71                 @Override\r
72                 public void onNoteOn(int channel, int key, final int velocity) {\r
73                         final int index = key - 60;\r
74                         if (index >= 0 && index < 13) {\r
75                                 runOnUiThread(new Runnable() {\r
76                                         @Override\r
77                                         public void run() {\r
78                                                 if (velocity > 0) keyDown(index);\r
79                                                 else keyUp(index);\r
80                                         }       \r
81                                 });\r
82                         }\r
83                 }\r
84 \r
85                 @Override public void onNoteOff(int channel, int key, int velocity) {\r
86                         final int index = key - 60;\r
87                         if (index >=0 && index < 13) {\r
88                                 runOnUiThread(new Runnable() {\r
89                                         @Override\r
90                                         public void run() {\r
91                                                 keyUp(index);\r
92                                         }       \r
93                                 });\r
94                         }\r
95                 }\r
96 \r
97                 // We won't use the remaining callbacks in this demo.\r
98                 @Override public void onProgramChange(int channel, int program) {}\r
99                 @Override public void onPolyAftertouch(int channel, int key, int velocity) {}\r
100                 @Override public void onPitchBend(int channel, int value) {}\r
101                 @Override public void onControlChange(int channel, int controller, int value) {}\r
102                 @Override public void onAftertouch(int channel, int velocity) {}\r
103         };\r
104 \r
105         private final ServiceConnection connection = new ServiceConnection() {\r
106                 @Override\r
107                 public void onServiceConnected(ComponentName name, IBinder service) {\r
108                         midiService = ((BluetoothMidiService.BluetoothMidiBinder)service).getService();\r
109                         try {\r
110                                 midiService.init();\r
111                                 midiService.setReceiver(receiver);\r
112                         } catch (IOException e) {\r
113                                 toast("MIDI not available");\r
114                                 finish();\r
115                         }\r
116                 }\r
117 \r
118                 @Override\r
119                 public void onServiceDisconnected(ComponentName name) {\r
120                         // this method will never be called\r
121                 }\r
122         };\r
123 \r
124         private void toast(final String msg) {\r
125                 runOnUiThread(new Runnable() {\r
126                         @Override\r
127                         public void run() {\r
128                                 Toast.makeText(getApplicationContext(), TAG + ": " + msg, Toast.LENGTH_SHORT).show();\r
129                         }\r
130                 });\r
131         }\r
132 \r
133         @Override\r
134         protected void onCreate(Bundle bundle) {\r
135                 super.onCreate(bundle);\r
136                 setContentView(R.layout.main);\r
137                 ImageButton white1 = (ImageButton) findViewById(R.id.white1);\r
138                 ImageButton white2 = (ImageButton) findViewById(R.id.white2);\r
139                 ImageButton white3 = (ImageButton) findViewById(R.id.white3);\r
140                 ImageButton white4 = (ImageButton) findViewById(R.id.white4);\r
141                 ImageButton white5 = (ImageButton) findViewById(R.id.white5);\r
142                 ImageButton white6 = (ImageButton) findViewById(R.id.white6);\r
143                 ImageButton white7 = (ImageButton) findViewById(R.id.white7);\r
144                 ImageButton white8 = (ImageButton) findViewById(R.id.white8);\r
145                 ImageButton black1 = (ImageButton) findViewById(R.id.black1);\r
146                 ImageButton black2 = (ImageButton) findViewById(R.id.black2);\r
147                 ImageButton black3 = (ImageButton) findViewById(R.id.black3);\r
148                 ImageButton black4 = (ImageButton) findViewById(R.id.black4);\r
149                 ImageButton black5 = (ImageButton) findViewById(R.id.black5);\r
150                 white1.setTag(0);\r
151                 white2.setTag(2);\r
152                 white3.setTag(4);\r
153                 white4.setTag(5);\r
154                 white5.setTag(7);\r
155                 white6.setTag(9);\r
156                 white7.setTag(11);\r
157                 white8.setTag(12);\r
158                 black1.setTag(1);\r
159                 black2.setTag(3);\r
160                 black3.setTag(6);\r
161                 black4.setTag(8);\r
162                 black5.setTag(10);\r
163                 keys = new ImageButton[] { white1, black1, white2, black2, white3,\r
164                                 white4, black3, white5, black4, white6, black5, white7, white8};\r
165                 for(ImageButton key : keys) {\r
166                         key.setOnTouchListener(this);\r
167                 }\r
168                 bindService(new Intent(this, BluetoothMidiService.class), connection, BIND_AUTO_CREATE);\r
169         }\r
170 \r
171         @Override\r
172         protected void onDestroy() {\r
173                 super.onDestroy();\r
174                 cleanup();\r
175         }\r
176 \r
177         private void cleanup() {\r
178                 try {\r
179                         unbindService(connection);\r
180                 } catch (IllegalArgumentException e) {\r
181                         // already unbound\r
182                         midiService = null;\r
183                 }\r
184         }\r
185 \r
186         public boolean onTouch(View view, MotionEvent motionEvent) {\r
187                 if (!(view instanceof ImageButton)) return false;\r
188                 ImageButton key = (ImageButton) view;\r
189                 Object tag = key.getTag();\r
190                 if (tag == null || !(tag instanceof Integer)) return false;\r
191                 int index = (Integer) tag;\r
192                 int action = motionEvent.getAction();\r
193                 if (action == MotionEvent.ACTION_DOWN && !touchState) {\r
194                         touchState = true;\r
195                         try {\r
196                                 midiService.sendNoteOn(0, index + 60, 64);\r
197                         } catch (IOException e) {\r
198                                 Log.e(TAG, e.getMessage());\r
199                         }\r
200                         keyDown(index);\r
201                 } else if (action == MotionEvent.ACTION_UP  && touchState) {\r
202                         touchState = false;\r
203                         try {\r
204                                 midiService.sendNoteOff(0, index + 60, 64);\r
205                         } catch (IOException e) {\r
206                                 Log.e(TAG, e.getMessage());\r
207                         }\r
208                         keyUp(index);\r
209                 }\r
210                 return true;\r
211         }\r
212 \r
213         private void keyDown(int n) {\r
214                 keys[n].setImageResource(imageDown[n]);\r
215         }\r
216 \r
217         private void keyUp(int n) {\r
218                 keys[n].setImageResource(imageUp[n]);\r
219         }\r
220 \r
221         @Override\r
222         public boolean onCreateOptionsMenu(Menu menu) {\r
223                 MenuInflater inflater = getMenuInflater();\r
224                 inflater.inflate(R.menu.menu, menu);\r
225                 return true;\r
226         }\r
227 \r
228         @Override\r
229         public boolean onOptionsItemSelected(MenuItem item) {\r
230                 switch (item.getItemId()) {\r
231                 case R.id.connect_item:\r
232                         if (midiService.getState() == BluetoothSppConnection.State.NONE) {\r
233                                 startActivityForResult(new Intent(this, DeviceListActivity.class), CONNECT);\r
234                         } else {\r
235                                 midiService.stop();\r
236                         }\r
237                         return true;\r
238                 default:\r
239                         return super.onOptionsItemSelected(item);\r
240                 }\r
241         }\r
242 \r
243         @Override\r
244         public void onActivityResult(int requestCode, int resultCode, Intent data) {\r
245                 switch (requestCode) {\r
246                 case CONNECT:\r
247                         if (resultCode == Activity.RESULT_OK) {\r
248                                 String address = data.getExtras().getString(DeviceListActivity.DEVICE_ADDRESS);\r
249                                 try {\r
250                                         midiService.connect(address, new Intent(this, PianoActivity.class), "Select to return to BluetoothMidiDemo.");\r
251                                 } catch (IOException e) {\r
252                                         toast(e.getMessage());\r
253                                 }                \r
254                         }\r
255                         break;\r
256                 }\r
257         }\r
258 }\r