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

Contents of /jsampler/trunk/src/org/jsampler/android/view/classic/MainFrame.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: 12952 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.CC;
29 import org.jsampler.HF;
30 import org.jsampler.JSPrefs;
31 import org.jsampler.Server;
32 import org.jsampler.android.AHF;
33 import org.jsampler.android.JSamplerActivity;
34 import org.jsampler.android.R;
35 import org.jsampler.android.view.AndroidChannelsPane;
36 import org.jsampler.android.view.AndroidMainFrame;
37 import org.jsampler.event.SamplerAdapter;
38 import org.jsampler.event.SamplerEvent;
39
40 import android.content.Context;
41 import android.os.Parcelable;
42 import android.support.v4.view.PagerAdapter;
43 import android.support.v4.view.ViewPager;
44 import android.util.Log;
45 import android.view.LayoutInflater;
46 import android.view.MotionEvent;
47 import android.view.View;
48 import android.widget.ImageButton;
49 import android.widget.SeekBar;
50 import android.widget.TextView;
51 import android.widget.ViewFlipper;
52
53 import static org.jsampler.JSPrefs.MAXIMUM_MASTER_VOLUME;
54 import static org.jsampler.JSPrefs.VOL_MEASUREMENT_UNIT_DECIBEL;
55 import static org.jsampler.android.view.AndroidI18n.i18n;
56 import static org.jsampler.android.view.classic.ClassicPrefs.preferences;
57 import static org.jsampler.android.JSamplerActivity.*;
58
59 public class MainFrame extends AndroidMainFrame<AndroidChannelsPane> {
60 private static final int FLING_MIN_DISTANCE = 100;
61
62 private View view = null;
63 private ViewFlipper panesFlipper;
64 private ViewPager lanesPager;
65
66 public MainFrame() {
67
68 }
69
70 @Override
71 public void
72 onCreate() {
73 LayoutInflater inflater =
74 (LayoutInflater)AHF.getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
75 view = inflater.inflate(R.layout.classic_main, null);
76
77 ChannelLanesPagerAdapter lanesPagerAdapter = new ChannelLanesPagerAdapter();
78 lanesPager = (ViewPager)view.findViewById(R.id.main_channel_lane_pager);
79 lanesPager.setAdapter(lanesPagerAdapter);
80
81 panesFlipper = (ViewFlipper)view.findViewById(R.id.main_flipper);
82 panesFlipper.setDisplayedChild(1);
83 updateMainTitle();
84
85 installListeners();
86 updateVolume();
87
88 ChannelsPane cp = new ChannelsPane();
89 cp.setTitle("Channel Lane 1");
90 addChannelsPane(cp);
91
92 addChannelsPane(new ChannelsPane("Channel Lane 2"));
93 setSelectedChannelsPane(cp);
94 }
95
96 public void
97 uninstall() {
98 uninstallListeners();
99 }
100
101 @Override
102 public View
103 getView() { return view; }
104
105 @Override
106 public boolean
107 onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
108 /*ViewFlipper flipper = getFlipper();
109
110 if(Math.abs(e1.getX() - e2.getX()) > Math.abs(e1.getY() - e2.getY())) {
111 if(Math.abs(e1.getX() - e2.getX()) < FLING_MIN_DISTANCE) return false;
112 if(e1.getX() - e2.getX() > 0) { // right to left
113 flipper.setInAnimation(AHF.inFromRightAnimation());
114 flipper.setOutAnimation(AHF.outToLeftAnimation());
115 flipper.showNext();
116 } else { // left to right
117 flipper.setInAnimation(AHF.inFromLeftAnimation());
118 flipper.setOutAnimation(AHF.outToRightAnimation());
119 flipper.showPrevious();
120 }
121 return true;
122 } else {
123 if(e1.getY() - e2.getY() > 0) { // up
124
125 } else { // down
126
127 }
128 }*/
129 return false;
130 }
131
132 public boolean
133 onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
134
135 return false;
136 }
137
138 @Override
139 public void setVisible(boolean b) {
140
141 }
142
143 private void
144 installListeners() {
145 SeekBar sliderVolume = (SeekBar)view.findViewById(R.id.main_slider_volume);
146 int i = CC.preferences().getIntProperty(MAXIMUM_MASTER_VOLUME);
147 sliderVolume.setMax(i);
148 CC.preferences().addPropertyChangeListener(MAXIMUM_MASTER_VOLUME, getHandler());
149
150 sliderVolume.setOnSeekBarChangeListener(getHandler());
151
152 CC.getSamplerModel().addSamplerListener(getHandler());
153
154 CC.preferences().addPropertyChangeListener(VOL_MEASUREMENT_UNIT_DECIBEL, getHandler());
155
156 ImageButton btn = (ImageButton)view.findViewById(R.id.classic_main_flip_back);
157 btn.setOnClickListener(new View.OnClickListener() {
158 public void onClick(View v) {
159 panesFlipper.setInAnimation(AHF.inFromLeftAnimation());
160 panesFlipper.setOutAnimation(AHF.outToRightAnimation());
161 panesFlipper.showPrevious();
162 updateMainTitle();
163 }
164 });
165
166 btn = (ImageButton)view.findViewById(R.id.classic_main_flip_forward);
167 btn.setOnClickListener(new View.OnClickListener() {
168 public void onClick(View v) {
169 panesFlipper.setInAnimation(AHF.inFromRightAnimation());
170 panesFlipper.setOutAnimation(AHF.outToLeftAnimation());
171 panesFlipper.showNext();
172 updateMainTitle();
173 }
174 });
175 }
176
177 private void
178 uninstallListeners() {
179 CC.preferences().removePropertyChangeListener(MAXIMUM_MASTER_VOLUME, getHandler());
180 CC.getSamplerModel().removeSamplerListener(getHandler());
181 CC.preferences().removePropertyChangeListener(VOL_MEASUREMENT_UNIT_DECIBEL, getHandler());
182
183 ImageButton btn = (ImageButton)view.findViewById(R.id.classic_main_flip_back);
184 btn.setOnClickListener(null);
185
186 btn = (ImageButton)view.findViewById(R.id.classic_main_flip_forward);
187 btn.setOnClickListener(null);
188
189 SeekBar sliderVolume = (SeekBar)view.findViewById(R.id.main_slider_volume);
190 sliderVolume.setOnSeekBarChangeListener(null);
191 }
192
193 private void
194 updateMainTitle() {
195 TextView text = (TextView)view.findViewById(R.id.main_title);
196 switch(panesFlipper.getDisplayedChild()) {
197 case 0:
198 text.setText(i18n.getLabel("MainFrame.titleMidiDevices"));
199 break;
200 case 1:
201 text.setText(i18n.getLabel("MainFrame.titleSamplerChannels"));
202 break;
203 case 2:
204 text.setText(i18n.getLabel("MainFrame.titleAudioDevices"));
205 break;
206 default:
207 text.setText("");
208 }
209 }
210
211 private void
212 updateVolume() {
213 SeekBar sliderVolume = (SeekBar)view.findViewById(R.id.main_slider_volume);
214 sliderVolume.setProgress((int)(CC.getSamplerModel().getVolume() * 100));
215 }
216
217 private void
218 setVolume(boolean isAdjusting) {
219 SeekBar sliderVolume = (SeekBar)view.findViewById(R.id.main_slider_volume);
220 TextView tvVolume = (TextView)view.findViewById(R.id.main_text_volume);
221 int volume = sliderVolume.getProgress();
222
223 tvVolume.setText(HF.getVolumeString(volume));
224
225 if(isAdjusting) return;
226
227 int vol = (int)(CC.getSamplerModel().getVolume() * 100);
228
229 if(vol == sliderVolume.getProgress()) return;
230
231 /*
232 * If the model's volume is not equal to the slider
233 * value we assume that the change is due to user input.
234 * So we must update the volume at the backend too.
235 */
236 float v = sliderVolume.getProgress();
237 v /= 100;
238 CC.getSamplerModel().setBackendVolume(v);
239 }
240
241 EventHandler handler = new EventHandler();
242
243 private EventHandler
244 getHandler() { return handler; }
245
246 private class EventHandler extends SamplerAdapter
247 implements SeekBar.OnSeekBarChangeListener, PropertyChangeListener {
248
249 @Override
250 public void
251 volumeChanged(SamplerEvent e) { updateVolume(); }
252
253 @Override
254 public void
255 onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
256 setVolume(true);
257 }
258
259 @Override
260 public void
261 onStopTrackingTouch(SeekBar seekBar) { setVolume(false); }
262
263 @Override
264 public void
265 onStartTrackingTouch(SeekBar seekBar) { }
266
267 @Override
268 public void
269 propertyChange(PropertyChangeEvent e) {
270 if (VOL_MEASUREMENT_UNIT_DECIBEL.equals(e.getPropertyName())) {
271 setVolume(true);
272 } else if (MAXIMUM_MASTER_VOLUME.equals(e.getPropertyName())) {
273 int j = CC.preferences().getIntProperty(MAXIMUM_MASTER_VOLUME);
274 SeekBar sliderVolume = (SeekBar)view.findViewById(R.id.main_slider_volume);
275 sliderVolume.setMax(j);
276 }
277
278 }
279 }
280
281 /**
282 * Gets the channels' pane that is currently shown,
283 * or has the focus if more than one channels' panes are shown.
284 * If the GUI implementation has only one pane containing sampler channels,
285 * than this method should always return that pane (the channels' pane
286 * with index 0).
287 * @return The selected channels' pane.
288 */
289 @Override
290 public AndroidChannelsPane
291 getSelectedChannelsPane() {
292 return getChannelsPane(lanesPager.getCurrentItem());
293 }
294
295 /**
296 * Sets the channels' pane to be selected.
297 * Note that all registered listeners should be notified
298 * when the selection is changed.
299 * @param pane The channels' pane to be shown.
300 * @see #fireChannelsPaneSelectionChanged
301 */
302 @Override
303 public void
304 setSelectedChannelsPane(AndroidChannelsPane pane) {
305 int idx = getChannelsPaneIndex(pane);
306 if(idx == -1) {
307 Log.w("setSelectedChannelsPane", "Channel lane not found!");
308 return;
309 }
310 lanesPager.setCurrentItem(idx, true);
311 }
312
313 /**
314 * Inserts the specified channels' pane at the specified position
315 * in the view and in the channels' pane list.
316 * Where and how this pane will be shown depends on the view/GUI implementation.
317 * Note that some GUI implementation may have only one pane containing sampler channels.
318 * @param pane The channels' pane to be inserted.
319 * @param idx Specifies the position of the channels' pane.
320 * @see #getChannelsPaneList
321 */
322 @Override
323 public void insertChannelsPane(AndroidChannelsPane pane, int idx) {
324 chnPaneList.insertElementAt(pane, idx);
325 lanesPager.getAdapter().notifyDataSetChanged();
326 lanesPager.setCurrentItem(idx, true);
327
328 /*ViewFlipper flipper = getFlipper();
329
330 if(idx < 0 || flipper.getChildCount() < idx) {
331 Log.w("classic.MainFrame.insertChannelsPane", "Incorrect lane position: " + idx);
332 flipper.addView(pane.getView());
333 } else {
334 flipper.addView(pane.getView(), idx);
335 }
336
337 flipper.setDisplayedChild(idx);*/
338 firePropertyChange("channelLaneAdded", null, pane);
339 }
340
341 /**
342 * Invoked on startup when no JSampler home directory is specified
343 * or the specified JSampler home directory doesn't exist.
344 * This method should ask the user to specify a JSampler
345 * home directory and then set the specified JSampler home directory using
346 * {@link org.jsampler.CC#setJSamplerHome} method.
347 * @see org.jsampler.CC#getJSamplerHome
348 * @see org.jsampler.CC#setJSamplerHome
349 */
350 @Override
351 public void installJSamplerHome() {
352 AHF.getActivity().showDialog(JSamplerActivity.DLG_CHOOSE_HOME_DIR);
353 }
354
355 /** Shows a detailed error information about the specified exception. */
356 @Override
357 public void showDetailedErrorMessage(String err, String details) {
358
359 }
360
361 @Override
362 public void handleConnectionFailure() {
363
364 }
365
366 /**
367 * Gets the server address to which to connect. If the server should be
368 * manually selected, a dialog asking the user to choose a server is displayed.
369 * @param manualSelect Determines whether the server should be manually selected.
370 */
371 @Override
372 public void getServer(final CC.Run<Server> r, boolean manualSelect) {
373 if(!manualSelect) {
374 int i = preferences().getIntProperty(JSPrefs.SERVER_INDEX);
375 int size = CC.getServerList().getServerCount();
376 if(size == 0) r.run(null);
377 else if(i >= size) r.run(CC.getServerList().getServer(0));
378 else r.run(CC.getServerList().getServer(i));
379 return;
380 }
381
382 AHF.getActivity().startLocalActivity(new Requestor<Server>(CHOOSE_BACKEND_REQUEST) {
383 public void
384 onResult(Server res) { r.run(res); }
385 });
386 }
387
388 /**
389 * Sends the specified script to the backend.
390 * @param script The file name of the script to run.
391 */
392 @Override
393 public void runScript(String script) {
394
395 }
396
397 private class ChannelLanesPagerAdapter extends PagerAdapter {
398 public int
399 getCount() { return getChannelsPaneCount(); }
400
401 public void startUpdate(View container) { }
402 public void finishUpdate(View container) { }
403
404 public Object
405 instantiateItem(View container, int position) {
406 View view = getChannelsPane(position).getView();
407 ((ViewPager)container).addView(view, 0);
408 return view;
409 }
410
411 public void
412 destroyItem(View container, int position, Object object) {
413 ((ViewPager)container).removeView((View)object);
414 }
415
416 public void
417 setPrimaryItem(View container, int position, Object object) {
418 setSelectedChannelsPane(getChannelsPane(position));
419 }
420
421 public boolean
422 isViewFromObject(View view, Object object) { return view == object; }
423
424 public Parcelable
425 saveState() { return null; }
426
427 public void
428 restoreState(Parcelable state, ClassLoader loader) { }
429 }
430 }

  ViewVC Help
Powered by ViewVC