/[svn]/jsampler/trunk/src/org/jsampler/android/view/classic/Channel.java
ViewVC logotype

Contents of /jsampler/trunk/src/org/jsampler/android/view/classic/Channel.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2302 - (show annotations) (download)
Thu Dec 15 23:13:30 2011 UTC (12 years, 4 months ago) by iliev
File size: 18622 byte(s)
* Initial support for Android platforms (only sampler channel
  manipulation for now - see the screenshots on the website)

1 /*
2 * JSampler - a java front-end for LinuxSampler
3 *
4 * Copyright (C) 2011 Grigor Iliev <grigor@grigoriliev.com>
5 *
6 * This file is part of JSampler.
7 *
8 * JSampler is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2
10 * as published by the Free Software Foundation.
11 *
12 * JSampler is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with JSampler; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * MA 02111-1307 USA
21 */
22
23 package org.jsampler.android.view.classic;
24
25 import java.beans.PropertyChangeEvent;
26 import java.beans.PropertyChangeListener;
27
28 import org.jsampler.AudioDeviceModel;
29 import org.jsampler.CC;
30 import org.jsampler.HF;
31 import org.jsampler.MidiDeviceModel;
32 import org.jsampler.MidiInstrumentMap;
33 import org.jsampler.SamplerChannelModel;
34 import org.jsampler.android.AHF;
35 import org.jsampler.android.R;
36 import org.jsampler.android.view.AndroidChannel;
37 import org.jsampler.android.view.AudioDeviceSpinnerAdapter;
38 import org.jsampler.android.view.EngineSpinnerAdapter;
39 import org.jsampler.android.view.MidiChannelSpinnerAdapter;
40 import org.jsampler.android.view.MidiDeviceSpinnerAdapter;
41 import org.jsampler.android.view.MidiMapSpinnerAdapter;
42 import org.jsampler.android.view.MidiPortSpinnerAdapter;
43 import org.jsampler.event.SamplerChannelEvent;
44 import org.jsampler.event.SamplerChannelListener;
45 import org.linuxsampler.lscp.MidiPort;
46 import org.linuxsampler.lscp.SamplerChannel;
47 import org.linuxsampler.lscp.SamplerEngine;
48
49 import android.content.Context;
50 import android.database.DataSetObserver;
51 import android.util.Log;
52 import android.view.LayoutInflater;
53 import android.view.View;
54 import android.widget.AdapterView.OnItemSelectedListener;
55 import android.widget.AdapterView;
56 import android.widget.SeekBar;
57 import android.widget.Spinner;
58 import android.widget.TextView;
59 import android.widget.ToggleButton;
60
61 import static org.jsampler.JSPrefs.*;
62 import static org.jsampler.android.view.AndroidI18n.i18n;
63
64 public class Channel extends AndroidChannel {
65 private View view = null;
66
67 public Channel(SamplerChannelModel model) {
68 super(model);
69 }
70
71 public View
72 getView() { return view; }
73
74 public void
75 installView(View viewToReuse) {
76 if(viewToReuse != null) view = viewToReuse;
77 else view = createView();
78
79 installListeners(); // don't change order
80 updateView();
81 }
82
83 public void
84 uninstallView() {
85 uninstallListeners(); // don't change order
86 view = null;
87 }
88
89 private void
90 installListeners() {
91 getModel().addSamplerChannelListener(getHandler());
92 CC.preferences().addPropertyChangeListener(VOL_MEASUREMENT_UNIT_DECIBEL, getHandler());
93
94 SeekBar slider = (SeekBar)view.findViewById(R.id.sampler_channel_slider_volume);
95 int i = CC.preferences().getIntProperty(MAXIMUM_CHANNEL_VOLUME);
96 slider.setMax(i);
97
98 slider.setOnSeekBarChangeListener(getHandler());
99
100 CC.preferences().addPropertyChangeListener(MAXIMUM_CHANNEL_VOLUME, getHandler());
101
102 final ToggleButton tbMute = (ToggleButton)view.findViewById(R.id.sampler_channel_btn_mute);
103 tbMute.setOnClickListener(new View.OnClickListener() {
104 public void onClick(View v) {
105 getModel().setBackendMute(tbMute.isChecked());
106 }
107 });
108
109 final ToggleButton tbSolo = (ToggleButton)view.findViewById(R.id.sampler_channel_btn_solo);
110 tbSolo.setOnClickListener(new View.OnClickListener() {
111 public void onClick(View v) {
112 getModel().setBackendSolo(tbSolo.isChecked());
113 }
114 });
115
116 final Spinner spEngine = (Spinner)view.findViewById(R.id.sampler_channel_engine);
117 SamplerEngine se = getChannelInfo().getEngine();
118
119 int idx = ((EngineSpinnerAdapter)spEngine.getAdapter()).prepareForSelection(se);
120 spEngine.setSelection(idx);
121
122 spEngine.setOnItemSelectedListener(new OnItemSelectedListener() {
123 public void
124 onItemSelected(AdapterView<?> parent, View view, int position, long id) {
125 SamplerEngine e = (SamplerEngine)spEngine.getAdapter().getItem(position);
126 if(e == null) return;
127 int pos = ((EngineSpinnerAdapter)spEngine.getAdapter()).prepareForSelection(e);
128 if(pos != position) spEngine.setSelection(pos, false);
129 getModel().setBackendEngineType(e.getName());
130 }
131
132 public void
133 onNothingSelected(AdapterView<?> parent) { }
134 });
135
136 final Spinner spMidiDev = (Spinner)view.findViewById(R.id.sampler_channel_midi_device);
137 spMidiDev.setOnItemSelectedListener(new OnItemSelectedListener() {
138 public void
139 onItemSelected(AdapterView<?> parent, View view, int position, long id) {
140 MidiDeviceModel d = (MidiDeviceModel)spMidiDev.getAdapter().getItem(position);
141 if(d == null) return;
142 int pos = ((MidiDeviceSpinnerAdapter)spMidiDev.getAdapter()).prepareForSelection(d);
143 if(pos != position) spMidiDev.setSelection(pos, false);
144
145 if(d.getDeviceId() != getChannelInfo().getMidiInputDevice()) {
146 getModel().setBackendMidiInputDevice(d.getDeviceId());
147 }
148 }
149
150 public void
151 onNothingSelected(AdapterView<?> parent) { }
152 });
153
154 spMidiDev.getAdapter().registerDataSetObserver(midiDevDataSetObserver);
155
156 final Spinner spMidiPort = (Spinner)view.findViewById(R.id.sampler_channel_midi_port);
157 spMidiPort.setOnItemSelectedListener(new OnItemSelectedListener() {
158 public void
159 onItemSelected(AdapterView<?> parent, View view, int position, long id) {
160 MidiPort p = (MidiPort)spMidiPort.getAdapter().getItem(position);
161 if(p == null) return;
162 int pos = ((MidiPortSpinnerAdapter)spMidiPort.getAdapter()).prepareForSelection(p);
163 if(pos != position) spMidiPort.setSelection(pos, false);
164
165 if(pos != getChannelInfo().getMidiInputPort()) {
166 getModel().setBackendMidiInputPort(pos);
167 }
168 }
169
170 public void
171 onNothingSelected(AdapterView<?> parent) { }
172 });
173
174 final Spinner spMidiChn = (Spinner)view.findViewById(R.id.sampler_channel_midi_channel);
175 spMidiChn.setOnItemSelectedListener(new OnItemSelectedListener() {
176 public void
177 onItemSelected(AdapterView<?> parent, View view, int position, long id) {
178 String chn = (String)spMidiChn.getAdapter().getItem(position);
179 if(chn == null) return;
180 int pos = ((MidiChannelSpinnerAdapter)spMidiChn.getAdapter()).prepareForSelection(chn);
181 if(pos != position) spMidiChn.setSelection(pos, false);
182
183 if(pos == 0) pos = -1; // All channels
184 else pos--; // convert to zero-based numbering
185 if(pos != getChannelInfo().getMidiInputChannel()) {
186 getModel().setBackendMidiInputChannel(pos);
187 }
188 }
189
190 public void
191 onNothingSelected(AdapterView<?> parent) { }
192 });
193
194 final Spinner spMidiMap = (Spinner)view.findViewById(R.id.sampler_channel_midi_map);
195 spMidiMap.setOnItemSelectedListener(new OnItemSelectedListener() {
196 public void
197 onItemSelected(AdapterView<?> parent, View view, int position, long id) {
198 Object map = spMidiMap.getAdapter().getItem(position);
199 if(map == null) return;
200 int pos = ((MidiMapSpinnerAdapter)spMidiMap.getAdapter()).prepareForSelection(map);
201 if(pos != position) spMidiMap.setSelection(pos, false);
202
203 if(map == MidiMapSpinnerAdapter.noMap) pos = -1;
204 else if(map == MidiMapSpinnerAdapter.defaultMap) pos = -2;
205 else pos = ((MidiInstrumentMap)map).getMapId();
206 if(pos != getChannelInfo().getMidiInstrumentMapId()) {
207 getModel().setBackendMidiInstrumentMap(pos);
208 }
209 }
210
211 public void
212 onNothingSelected(AdapterView<?> parent) { }
213 });
214
215 spMidiMap.getAdapter().registerDataSetObserver(midiMapDataSetObserver);
216
217 final Spinner spAudioDev = (Spinner)view.findViewById(R.id.sampler_channel_audio_device);
218 spAudioDev.setOnItemSelectedListener(new OnItemSelectedListener() {
219 public void
220 onItemSelected(AdapterView<?> parent, View view, int position, long id) {
221 AudioDeviceModel d = (AudioDeviceModel)spAudioDev.getAdapter().getItem(position);
222 if(d == null) return;
223 int pos = ((AudioDeviceSpinnerAdapter)spAudioDev.getAdapter()).prepareForSelection(d);
224 if(pos != position) spAudioDev.setSelection(pos, false);
225
226 if(d.getDeviceId() != getChannelInfo().getAudioOutputDevice()) {
227 getModel().setBackendAudioOutputDevice(d.getDeviceId());
228 }
229 }
230
231 public void
232 onNothingSelected(AdapterView<?> parent) { }
233 });
234
235 spAudioDev.getAdapter().registerDataSetObserver(audioDevDataSetObserver);
236 }
237
238 private void
239 uninstallListeners() {
240 getModel().removeSamplerChannelListener(getHandler());
241 CC.preferences().removePropertyChangeListener(VOL_MEASUREMENT_UNIT_DECIBEL, getHandler());
242 CC.preferences().removePropertyChangeListener(MAXIMUM_CHANNEL_VOLUME, getHandler());
243
244 ToggleButton tb = (ToggleButton)view.findViewById(R.id.sampler_channel_btn_mute);
245 tb.setOnClickListener(null);
246
247 tb = (ToggleButton)view.findViewById(R.id.sampler_channel_btn_solo);
248 tb.setOnClickListener(null);
249
250 SeekBar slider = (SeekBar)view.findViewById(R.id.sampler_channel_slider_volume);
251 slider.setOnSeekBarChangeListener(null);
252
253 Spinner spinner = (Spinner)view.findViewById(R.id.sampler_channel_engine);
254 spinner.setOnItemSelectedListener(null);
255
256 spinner = (Spinner)view.findViewById(R.id.sampler_channel_midi_device);
257 spinner.setOnItemSelectedListener(null);
258 spinner.getAdapter().unregisterDataSetObserver(midiDevDataSetObserver);
259
260 spinner = (Spinner)view.findViewById(R.id.sampler_channel_midi_port);
261 spinner.setOnItemSelectedListener(null);
262
263 spinner = (Spinner)view.findViewById(R.id.sampler_channel_midi_channel);
264 spinner.setOnItemSelectedListener(null);
265
266 spinner = (Spinner)view.findViewById(R.id.sampler_channel_midi_map);
267 spinner.setOnItemSelectedListener(null);
268 spinner.getAdapter().unregisterDataSetObserver(midiMapDataSetObserver);
269
270 spinner = (Spinner)view.findViewById(R.id.sampler_channel_audio_device);
271 spinner.setOnItemSelectedListener(null);
272 spinner.getAdapter().unregisterDataSetObserver(audioDevDataSetObserver);
273 }
274
275 /* Used to update the spinner selection in case it was invalidated
276 * due to removal of an item which was before the selected item. */
277 private DataSetObserver midiDevDataSetObserver = new DataSetObserver() {
278 public void
279 onChanged() { updateMidiDevice(); }
280 };
281
282 /* Used to update the spinner selection in case it was invalidated
283 * due to removal of an item which was before the selected item. */
284 private DataSetObserver midiMapDataSetObserver = new DataSetObserver() {
285 public void
286 onChanged() { updateMidiMap(); }
287 };
288
289 /* Used to update the spinner selection in case it was invalidated
290 * due to removal of an item which was before the selected item. */
291 private DataSetObserver audioDevDataSetObserver = new DataSetObserver() {
292 public void
293 onChanged() { updateAudioDevice(); }
294 };
295
296 public View
297 createView() {
298 LayoutInflater inflater =
299 (LayoutInflater)AHF.getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
300 View v = inflater.inflate(R.layout.sampler_channel, null);
301
302 Spinner spinner = (Spinner)v.findViewById(R.id.sampler_channel_engine);
303 spinner.setAdapter(new EngineSpinnerAdapter());
304
305 spinner = (Spinner)v.findViewById(R.id.sampler_channel_midi_device);
306 spinner.setAdapter(new MidiDeviceSpinnerAdapter());
307
308 spinner = (Spinner)v.findViewById(R.id.sampler_channel_midi_port);
309 spinner.setAdapter(new MidiPortSpinnerAdapter());
310
311 spinner = (Spinner)v.findViewById(R.id.sampler_channel_midi_channel);
312 spinner.setAdapter(new MidiChannelSpinnerAdapter());
313
314 spinner = (Spinner)v.findViewById(R.id.sampler_channel_midi_map);
315 spinner.setAdapter(new MidiMapSpinnerAdapter());
316
317 spinner = (Spinner)v.findViewById(R.id.sampler_channel_audio_device);
318 spinner.setAdapter(new AudioDeviceSpinnerAdapter());
319
320 return v;
321 }
322
323 public void
324 updateView() {
325 int num = CC.getMainFrame().getChannelNumber(getModel()) + 1;
326 TextView text = (TextView)view.findViewById(R.id.sampler_channel_title);
327 text.setText(i18n.getLabel("Channel.title", num));
328
329 SamplerChannel sc = getChannelInfo();
330 boolean b = sc.getEngine() != null;
331
332 ToggleButton toggleBtn = (ToggleButton)view.findViewById(R.id.sampler_channel_btn_solo);
333 toggleBtn.setChecked(sc.isSoloChannel());
334 toggleBtn.setEnabled(b);
335
336 toggleBtn = (ToggleButton)view.findViewById(R.id.sampler_channel_btn_mute);
337 toggleBtn.setChecked(sc.isMuted() && !sc.isMutedBySolo());
338 toggleBtn.setEnabled(b);
339
340 SeekBar slider = (SeekBar)view.findViewById(R.id.sampler_channel_slider_volume);
341 slider.setEnabled(b);
342 updateVolume(slider);
343
344 updateMidiDevice();
345 updateEngine();
346 updateMidiPort();
347 updateMidiChannel();
348 updateMidiMap();
349 updateAudioDevice();
350 }
351
352 private void
353 updateVolume(SeekBar slider) {
354 slider.setProgress((int)(getChannelInfo().getVolume() * 100));
355 }
356
357 private void
358 updateEngine() {
359 Spinner spinner = (Spinner)view.findViewById(R.id.sampler_channel_engine);
360 SamplerEngine se = getChannelInfo().getEngine();
361 int pos = ((EngineSpinnerAdapter)spinner.getAdapter()).prepareForSelection(se);
362 if(pos >= 0) {
363 if(pos != spinner.getSelectedItemPosition()) {
364 spinner.setSelection(pos);
365 }
366 } else {
367 Log.w("view.Channel", "Engine not found in spinner. This is a bug!");
368 }
369 }
370
371 private void
372 updateMidiDevice() {
373 Spinner spinner = (Spinner)view.findViewById(R.id.sampler_channel_midi_device);
374 int id = getChannelInfo().getMidiInputDevice();
375 MidiDeviceModel dev = null;
376 if(id != -1) dev = CC.getSamplerModel().getMidiDeviceById(id);
377
378 int pos = ((MidiDeviceSpinnerAdapter)spinner.getAdapter()).prepareForSelection(dev);
379 if(pos >= 0) {
380 if(pos != spinner.getSelectedItemPosition()) {
381 spinner.setSelection(pos);
382 }
383 } else {
384 Log.w("view.Channel", "MIDI device not found in spinner. This is a bug!");
385 }
386 }
387
388 private void
389 updateMidiPort() {
390 Spinner spinner = (Spinner)view.findViewById(R.id.sampler_channel_midi_port);
391 MidiPortSpinnerAdapter adapter = (MidiPortSpinnerAdapter)spinner.getAdapter();
392 int id = getChannelInfo().getMidiInputDevice();
393 adapter.setMidiDevice(id);
394
395 if(id == -1) {
396 spinner.setSelection(adapter.prepareForSelection(null));
397 } else {
398 MidiDeviceModel dev = CC.getSamplerModel().getMidiDeviceById(id);
399 MidiPort p = dev.getDeviceInfo().getMidiPort(getChannelInfo().getMidiInputPort());
400
401 int idx = adapter.prepareForSelection(p);
402 if(idx != spinner.getSelectedItemPosition()) spinner.setSelection(idx);
403 }
404 }
405
406 private void
407 updateMidiChannel() {
408 Spinner spinner = (Spinner)view.findViewById(R.id.sampler_channel_midi_channel);
409 MidiChannelSpinnerAdapter adapter = (MidiChannelSpinnerAdapter)spinner.getAdapter();
410 int id = getChannelInfo().getMidiInputDevice();
411 adapter.setMidiDevice(id);
412
413 if(id == -1) {
414 spinner.setSelection(adapter.prepareForSelection(null));
415 } else {
416 String s;
417 int chn = getChannelInfo().getMidiInputChannel();
418 if(chn == -1) s = MidiChannelSpinnerAdapter.channels[0]; // all channels
419 else s = MidiChannelSpinnerAdapter.channels[chn + 1];
420
421 int idx = adapter.prepareForSelection(s);
422 if(idx != spinner.getSelectedItemPosition()) spinner.setSelection(idx);
423 }
424 }
425
426 private void
427 updateMidiMap() {
428 Spinner spinner = (Spinner)view.findViewById(R.id.sampler_channel_midi_map);
429 MidiMapSpinnerAdapter adapter = (MidiMapSpinnerAdapter)spinner.getAdapter();
430 if(getChannelInfo().getEngine() == null) {
431 spinner.setSelection(adapter.prepareForSelection(null));
432 spinner.setEnabled(false);
433 } else {
434 spinner.setEnabled(true);
435 Object o;
436 int mapId = getChannelInfo().getMidiInstrumentMapId();
437 if(mapId == -2) o = MidiMapSpinnerAdapter.defaultMap;
438 else if(mapId == -1) o = MidiMapSpinnerAdapter.noMap;
439 else o = CC.getSamplerModel().getMidiInstrumentMapById(mapId);
440
441 if(o == null) Log.w("view.classic.Channel", "Unknown map. This is a bug!");
442
443 int idx = adapter.prepareForSelection(o);
444 if(idx != spinner.getSelectedItemPosition()) spinner.setSelection(idx);
445 }
446 }
447
448 private void
449 updateAudioDevice() {
450 Spinner spinner = (Spinner)view.findViewById(R.id.sampler_channel_audio_device);
451 int id = getChannelInfo().getAudioOutputDevice();
452 AudioDeviceModel dev = null;
453 if(id != -1) dev = CC.getSamplerModel().getAudioDeviceById(id);
454
455 int pos = ((AudioDeviceSpinnerAdapter)spinner.getAdapter()).prepareForSelection(dev);
456 if(pos >= 0) {
457 if(pos != spinner.getSelectedItemPosition()) {
458 spinner.setSelection(pos);
459 }
460 } else {
461 Log.w("view.Channel", "Audio device not found in spinner. This is a bug!");
462 }
463 }
464
465 private void
466 setVolume(boolean isAdjusting) {
467 SeekBar sliderVolume = (SeekBar)view.findViewById(R.id.sampler_channel_slider_volume);
468 TextView tvVolume = (TextView)view.findViewById(R.id.sampler_channel_text_volume);
469 int volume = sliderVolume.getProgress();
470
471 tvVolume.setText(HF.getVolumeString(volume));
472
473 if(isAdjusting) return;
474
475 int vol = (int)(getChannelInfo().getVolume() * 100);
476
477 if(vol == sliderVolume.getProgress()) return;
478
479 /*
480 * If the model's volume is not equal to the slider
481 * value we assume that the change is due to user input.
482 * So we must update the volume at the backend too.
483 */
484 float v = sliderVolume.getProgress();
485 v /= 100;
486 getModel().setBackendVolume(v);
487 }
488
489 EventHandler handler = new EventHandler();
490
491 private EventHandler
492 getHandler() { return handler; }
493
494 private class EventHandler implements SamplerChannelListener, PropertyChangeListener,
495 SeekBar.OnSeekBarChangeListener {
496 public void
497 channelChanged(SamplerChannelEvent e) {
498 updateView();
499 }
500
501 public void streamCountChanged(SamplerChannelEvent e) { }
502
503 public void voiceCountChanged(SamplerChannelEvent e) { }
504
505 public void
506 propertyChange(PropertyChangeEvent e) {
507 if(view == null) return;
508
509 if (VOL_MEASUREMENT_UNIT_DECIBEL.equals(e.getPropertyName())) {
510 setVolume(true);
511 } else if (MAXIMUM_CHANNEL_VOLUME.equals(e.getPropertyName())) {
512 int j = CC.preferences().getIntProperty(MAXIMUM_CHANNEL_VOLUME);
513 SeekBar v = (SeekBar)view.findViewById(R.id.sampler_channel_slider_volume);
514 v.setMax(j);
515 }
516 }
517
518 @Override
519 public void
520 onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
521 setVolume(true);
522 }
523
524 @Override
525 public void
526 onStopTrackingTouch(SeekBar seekBar) { setVolume(false); }
527
528 @Override
529 public void
530 onStartTrackingTouch(SeekBar seekBar) { }
531 }
532 }

  ViewVC Help
Powered by ViewVC