/[svn]/jsampler/trunk/src/org/jsampler/view/JSMainFrame.java
ViewVC logotype

Contents of /jsampler/trunk/src/org/jsampler/view/JSMainFrame.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1818 - (show annotations) (download)
Wed Dec 24 17:29:47 2008 UTC (15 years, 4 months ago) by iliev
File size: 13875 byte(s)
* Added support for controlling the global sampler-wide limit of
  maximum voices and disk streams
  (choose Edit/Preferences, then click the `General' tab)
* Fantasia: store the view configuration of audio/MIDI devices and sampler
  channels in the LSCP script when exporting sampler configuration
* Fantasia: Implemented multiple sampler channels' selection
* Fantasia: Added option to move sampler channels up and down
  in the channels list
* Fantasia: Added option to move sampler channels
  to another channels panels

1 /*
2 * JSampler - a java front-end for LinuxSampler
3 *
4 * Copyright (C) 2005-2008 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.view;
24
25 import java.awt.Dialog;
26 import java.awt.Frame;
27
28 import java.awt.event.ActionEvent;
29 import java.awt.event.KeyEvent;
30 import java.awt.event.WindowAdapter;
31 import java.awt.event.WindowEvent;
32
33 import java.util.Vector;
34 import java.util.logging.Level;
35
36 import javax.swing.AbstractAction;
37 import javax.swing.JComponent;
38 import javax.swing.JFrame;
39 import javax.swing.KeyStroke;
40
41 import javax.swing.event.ListSelectionEvent;
42 import javax.swing.event.ListSelectionListener;
43
44 import org.jsampler.CC;
45 import org.jsampler.JSampler;
46 import org.jsampler.SamplerChannelModel;
47 import org.jsampler.Server;
48
49 import org.jsampler.event.SamplerChannelListEvent;
50 import org.jsampler.event.SamplerChannelListListener;
51
52 import org.jsampler.view.SessionViewConfig.ChannelConfig;
53
54
55 /**
56 * Defines the skeleton of a JSampler's main frame.
57 * @author Grigor Iliev
58 */
59 public abstract class JSMainFrame extends JFrame {
60 private final Vector<JSChannelsPane> chnPaneList = new Vector<JSChannelsPane>();
61 private boolean autoUpdateChannelListUI = true;
62
63 /** Creates a new instance of <code>JSMainFrame</code>. */
64 public
65 JSMainFrame() {
66 super(JSampler.NAME + ' ' + JSampler.VERSION);
67
68 setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
69 addWindowListener(new WindowAdapter() {
70 public void
71 windowClosing(WindowEvent we) { onWindowClose(); }
72 });
73
74 CC.getSamplerModel().addSamplerChannelListListener(new EventHandler());
75
76 getRootPane().getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT).put (
77 KeyStroke.getKeyStroke(KeyEvent.VK_G, KeyEvent.CTRL_MASK | KeyEvent.SHIFT_MASK),
78 "RunGarbageCollector"
79 );
80
81 getRootPane().getActionMap().put ("RunGarbageCollector", new AbstractAction() {
82 public void
83 actionPerformed(ActionEvent e) {
84 System.gc();
85 }
86 });
87 }
88
89 /**
90 * Invoked when this window is about to close.
91 * Don't forget to call <code>super.onWindowClose()</code> at the end,
92 * when override this method.
93 */
94 protected void
95 onWindowClose() {
96 CC.cleanExit();
97 }
98
99 /**
100 * Invoked on startup when no JSampler home directory is specified
101 * or the specified JSampler home directory doesn't exist.
102 * This method should ask the user to specify a JSampler
103 * home directory and then set the specified JSampler home directory using
104 * {@link org.jsampler.CC#setJSamplerHome} method.
105 * @see org.jsampler.CC#getJSamplerHome
106 * @see org.jsampler.CC#setJSamplerHome
107 */
108 public abstract void installJSamplerHome();
109
110 /**
111 * Shows a detailed error information about the specified exception.
112 */
113 public abstract void showDetailedErrorMessage(Frame owner, String err, String details);
114
115 /**
116 * Shows a detailed error information about the specified exception.
117 */
118 public abstract void showDetailedErrorMessage(Dialog owner, String err, String details);
119
120 protected Vector<ListSelectionListener> channelsPaneListeners =
121 new Vector<ListSelectionListener>();
122
123 /**
124 * Registers the specified listener for receiving event messages.
125 * @param l The <code>ListSelectionListener</code> to register.
126 */
127 public void
128 addChannelsPaneSelectionListener(ListSelectionListener l) {
129 channelsPaneListeners.add(l);
130 }
131
132 /**
133 * Removes the specified listener.
134 * @param l The <code>ListSelectionListener</code> to remove.
135 */
136 public void
137 removeChannelsPaneSelectionListener(ListSelectionListener l) {
138 channelsPaneListeners.remove(l);
139 }
140
141 protected void
142 fireChannelsPaneSelectionChanged() {
143 int i = getChannelsPaneIndex(getSelectedChannelsPane());
144 ListSelectionEvent e = new ListSelectionEvent(this, i, i, false);
145 for(ListSelectionListener l : channelsPaneListeners) l.valueChanged(e);
146 }
147
148 /**
149 * Returns a list containing all <code>JSChannelsPane</code>s added to the view.
150 * @return A list containing all <code>JSChannelsPane</code>s added to the view.
151 * @see #addChannelsPane
152 * @see #removeChannelsPane
153 */
154 public Vector<JSChannelsPane>
155 getChannelsPaneList() { return chnPaneList; }
156
157 /**
158 * Return the <code>JSChannelsPane</code> at the specified position.
159 * @param idx The position of the <code>JSChannelsPane</code> to be returned.
160 * @return The <code>JSChannelsPane</code> at the specified position.
161 */
162 public JSChannelsPane
163 getChannelsPane(int idx) { return chnPaneList.get(idx); }
164
165 /**
166 * Adds the specified <code>JSChannelsPane</code> to the view.
167 * @param chnPane The <code>JSChannelsPane</code> to be added.
168 */
169 public void
170 addChannelsPane(JSChannelsPane chnPane) { chnPaneList.add(chnPane); }
171
172 /**
173 * Removes the specified <code>JSChannelsPane</code> from the view.
174 * Override this method to remove <code>chnPane</code> from the view,
175 * and don't forget to call <code>super.removeChannelsPane(chnPane);</code>.
176 * @param chnPane The <code>JSChannelsPane</code> to be removed.
177 * @return <code>true</code> if the specified code>JSChannelsPane</code>
178 * is actually removed from the view, <code>false</code> otherwise.
179 */
180 public boolean
181 removeChannelsPane(JSChannelsPane chnPane) { return chnPaneList.remove(chnPane); }
182
183 /**
184 * Gets the current number of <code>JSChannelsPane</code>s added to the view.
185 * @return The current number of <code>JSChannelsPane</code>s added to the view.
186 */
187 public int
188 getChannelsPaneCount() { return chnPaneList.size(); }
189
190 /**
191 * Returns the index of the specified channels pane, or -1 if
192 * the specified channels pane is not found.
193 */
194 public int
195 getChannelsPaneIndex(JSChannelsPane chnPane) {
196 return chnPaneList.indexOf(chnPane);
197 }
198
199 /**
200 * Inserts the specified <code>JSChannelsPane</code> at the specified position
201 * in the view and in the code>JSChannelsPane</code> list.
202 * Where and how this pane will be shown depends on the view/GUI implementation.
203 * Note that some GUI implementation may have only one pane containing sampler channels.
204 * @param pane The <code>JSChannelsPane</code> to be inserted.
205 * @param idx Specifies the position of the <code>JSChannelsPane</code>.
206 * @see #getChannelsPaneList
207 */
208 public abstract void insertChannelsPane(JSChannelsPane pane, int idx);
209
210 /**
211 * Gets the <code>JSChannelsPane</code> that is currently shown,
212 * or has the focus if more than one channels' panes are shown.
213 * If the GUI implementation has only one pane containing sampler channels,
214 * than this method should always return that pane (the <code>JSChannelsPane</code>
215 * with index 0).
216 * @return The selected <code>JSChannelsPane</code>.
217 */
218 public abstract JSChannelsPane getSelectedChannelsPane();
219
220 /**
221 * Gets the server address to which to connect. If the server should be
222 * manually selected, a dialog asking the user to choose a server is displayed.
223 */
224 public abstract Server getServer();
225
226 /**
227 * Gets the server address to which to connect. If the server should be
228 * manually selected, a dialog asking the user to choose a server is displayed.
229 * @param manualSelect Determines whether the server should be manually selected.
230 */
231 public abstract Server getServer(boolean manualSelect);
232
233 /**
234 * Sets the <code>JSChannelsPane</code> to be selected.
235 * Note that all registered listeners should be notified
236 * when the selection is changed.
237 * @param pane The <code>JSChannelsPane</code> to be shown.
238 * @see #fireChannelsPaneSelectionChanged
239 */
240 public abstract void setSelectedChannelsPane(JSChannelsPane pane);
241
242 private class EventHandler implements SamplerChannelListListener {
243 /**
244 * Invoked when a new sampler channel is created.
245 * @param e A <code>SamplerChannelListEvent</code>
246 * instance providing the event information.
247 */
248 @Override
249 public void
250 channelAdded(SamplerChannelListEvent e) {
251 if(e.getChannelModel() == null) return;
252 Integer id = e.getChannelModel().getChannelId();
253 if(findChannel(id) != null) {
254 CC.getLogger().log(Level.WARNING, "JSMainFrame.channelExist!", id);
255 return;
256 }
257
258 ChannelConfig config = null;
259 JSViewConfig viewConfig = CC.getViewConfig();
260 if(viewConfig != null && viewConfig.getSessionViewConfig() != null) {
261 config = viewConfig.getSessionViewConfig().pollChannelConfig();
262 }
263
264 if(config == null) {
265 getSelectedChannelsPane().addChannel(e.getChannelModel());
266 } else {
267 int i = config.channelsPanel;
268 if(i >= 0 && i < getChannelsPaneCount()) {
269 getChannelsPane(i).addChannel(e.getChannelModel(), config);
270 } else {
271 getSelectedChannelsPane().addChannel(e.getChannelModel(), config);
272 }
273 }
274 }
275
276 /**
277 * Invoked when a sampler channel is removed.
278 * @param e A <code>SamplerChannelListEvent</code>
279 * instance providing the event information.
280 */
281 @Override
282 public void
283 channelRemoved(SamplerChannelListEvent e) {
284 removeChannel(e.getChannelModel().getChannelId());
285 }
286 }
287
288 /**
289 * Searches for the first occurence of a channel with numerical ID <code>id</code>.
290 * @return The first occurence of a channel with numerical ID <code>id</code> or
291 * <code>null</code> if there is no channel with numerical ID <code>id</code>.
292 */
293 public JSChannel
294 findChannel(int id) {
295 if(id < 0) return null;
296
297 for(JSChannelsPane cp : getChannelsPaneList()) {
298 for(JSChannel c : cp.getChannels()) if(c.getChannelId() == id) return c;
299 }
300
301 return null;
302 }
303
304 /**
305 * Removes the first occurence of a channel with numerical ID <code>id</code>.
306 * This method is invoked when a sampler channel is removed in the back-end.
307 * @return The removed channel or <code>null</code>
308 * if there is no channel with numerical ID <code>id</code>.
309 */
310 public JSChannel
311 removeChannel(int id) {
312 if(id < 0) return null;
313
314 for(JSChannelsPane cp : getChannelsPaneList()) {
315 for(JSChannel c : cp.getChannels()) {
316 if(c.getChannelId() == id) {
317 cp.removeChannel(c);
318 return c;
319 }
320 }
321 }
322
323 return null;
324 }
325
326 /**
327 * Gets the zero-based position of the specified sampler channel
328 * in the channels pane, to which the channel is added.
329 * Note that the position may change when adding/removing sampler channels.
330 * @return The zero-based position of the specified sampler channel
331 * in the channels pane, or -1 if the specified channels is not found.
332 */
333 public int
334 getChannelNumber(SamplerChannelModel channel) {
335 if(channel == null) return -1;
336
337 for(int i = 0; i < getChannelsPaneCount(); i++) {
338 JSChannelsPane chnPane = getChannelsPane(i);
339 for(int j = 0; j < chnPane.getChannelCount(); j++) {
340 if(chnPane.getChannel(j).getChannelId() == channel.getChannelId()) {
341 return j;
342 }
343 }
344 }
345
346 return -1;
347 }
348
349 /**
350 * Returns a string in the format <code>channelPaneNumber/channelNumber</code>,
351 * where <code>channelPaneNumber</code> is the one-based number of the channels
352 * pane containing the specified channel and <code>channelNumber</code> is the
353 * one-based number of the channel's position in the channels pane.
354 * Note that this path may change when adding/removing channels/channels panes.
355 * @return The channels path, or <code>null</code> if the specified channels is not found.
356 */
357 public String
358 getChannelPath(SamplerChannelModel channel) {
359 if(channel == null) return null;
360
361 for(int i = 0; i < getChannelsPaneCount(); i++) {
362 JSChannelsPane chnPane = getChannelsPane(i);
363 for(int j = 0; j < chnPane.getChannelCount(); j++) {
364 if(chnPane.getChannel(j).getChannelId() == channel.getChannelId()) {
365 return (i + 1) + "." + (j + 1);
366 }
367 }
368 }
369
370 return null;
371 }
372
373 /**
374 * Gets the zero-based number of the channels pane,
375 * to which the specified sampler channel is added.
376 * Note that the can be moved from one channels pane to another.
377 * @return The zero-based index of the channels pane,
378 * to which the specified sampler channel is added, or
379 * -1 if the specified channels is not found.
380 */
381 public int
382 getChannelsPaneNumber(SamplerChannelModel channel) {
383 if(channel == null) return -1;
384
385 for(int i = 0; i < getChannelsPaneCount(); i++) {
386 JSChannelsPane chnPane = getChannelsPane(i);
387 for(int j = 0; j < chnPane.getChannelCount(); j++) {
388 if(chnPane.getChannel(j).getChannelId() == channel.getChannelId()) {
389 return i;
390 }
391 }
392 }
393
394 return -1;
395 }
396
397 /**
398 * Sends the specified script to the backend.
399 * @param script The file name of the script to run.
400 */
401 public abstract void runScript(String script);
402
403 /**
404 * Determines whether the channel list UI should be automatically updated
405 * when channel is added/removed. The default value is <code>true</code>.
406 */
407 public boolean
408 getAutoUpdateChannelListUI() { return autoUpdateChannelListUI; }
409
410 /**
411 * Determines whether the channel list UI should be automatically updated
412 * when channel is added/removed.
413 */
414 public void
415 setAutoUpdateChannelListUI(boolean b) {
416 if(b == autoUpdateChannelListUI) return;
417
418 autoUpdateChannelListUI = b;
419 for(JSChannelsPane cp : getChannelsPaneList()) {
420 cp.setAutoUpdate(b);
421 }
422 }
423
424 /**
425 * Updates the channel list UI.
426 */
427 public void
428 updateChannelListUI() {
429 for(JSChannelsPane cp : getChannelsPaneList()) {
430 cp.updateChannelListUI();
431 }
432 }
433 }

  ViewVC Help
Powered by ViewVC