# Example script to control audio objects with a simple GUI # # Author: Matthew Harris, copyright 2010 # Part of the JMRI distribution # # The next line is maintained by CVS, please don't change it # $Revision: 17977 $ from java.awt import FlowLayout from java.awt.event import ItemEvent from java.util import Hashtable from javax.swing import Box, BoxLayout, JButton, JComboBox, JPanel, JSlider, JLabel, JSpinner, SpinnerNumberModel from jmri.util import JmriJFrame from jmri.util.swing import VerticalLabelUI from jmri import Audio class AudioPlayerFrame (JmriJFrame): # Define the range for position values # By default, this is -10 to +10 range = 10 # Calculate slider range posMinMax = int(10**Audio.DECIMAL_PLACES) # Define controls playButton = JButton("Play") stopButton = JButton("Stop") pauseButton = JButton("Pause") refreshButton = JButton("Refresh") rangeSpinner = JSpinner(SpinnerNumberModel(range, 1, 100, 1)) sourceCombo = JComboBox() positionXSlider = JSlider() positionYSlider = JSlider() positionZSlider = JSlider() # Reference to AudioSource source = None # Define various constants PLAY = "AUDIO.PLAY" PAUSE = "AUDIO.PAUSE" RESUME = "AUDIO.RESUME" STOP = "AUDIO.STOP" REFRESH = "AUDIO.REFRESH" SELECT = "Select source from list" POSX = "X" POSY = "Y" POSZ = "Z" def __init__(self): # Setup controls - buttons first self.playButton.preferredSize = self.refreshButton.preferredSize self.playButton.actionCommand = self.PLAY self.playButton.actionPerformed = self.whenButtonClicked self.pauseButton.preferredSize = self.refreshButton.preferredSize self.pauseButton.actionCommand = self.PAUSE self.pauseButton.actionPerformed = self.whenButtonClicked self.stopButton.preferredSize = self.refreshButton.preferredSize self.stopButton.actionCommand = self.STOP self.stopButton.actionPerformed = self.whenButtonClicked self.refreshButton.actionCommand = self.REFRESH self.refreshButton.actionPerformed = self.whenButtonClicked # Now combobox and text field self.sourceCombo.itemStateChanged = self.whenSourceChanged self.updateSourcesList() self.rangeSpinner.stateChanged = self.whenRangeChanged # Now sliders ticksMajor = int(self.posMinMax/4) ticksMinor = int(ticksMajor/5) labels = Hashtable(3) labels.put(-self.posMinMax, JLabel("Left")) labels.put( 0, JLabel("Centre")) labels.put( self.posMinMax, JLabel("Right")) self.positionXSlider.labelTable = labels self.positionXSlider.minimum = -self.posMinMax self.positionXSlider.maximum = self.posMinMax self.positionXSlider.majorTickSpacing = ticksMajor self.positionXSlider.minorTickSpacing = ticksMinor self.positionXSlider.paintTicks = True self.positionXSlider.paintLabels = True self.positionXSlider.snapToTicks = True self.positionXSlider.value = 0 self.positionXSlider.stateChanged = self.whenSliderXChanged labels = Hashtable(3) labels.put(-self.posMinMax, JLabel("Behind")) labels.put( 0, JLabel("Centre")) labels.put( self.posMinMax, JLabel("In-front")) self.positionYSlider.labelTable = labels self.positionYSlider.minimum = -self.posMinMax self.positionYSlider.maximum = self.posMinMax self.positionYSlider.majorTickSpacing = ticksMajor self.positionYSlider.minorTickSpacing = ticksMinor self.positionYSlider.paintTicks = True self.positionYSlider.paintLabels = True self.positionYSlider.snapToTicks = True self.positionYSlider.value = 0 self.positionYSlider.orientation = JSlider.VERTICAL self.positionYSlider.stateChanged = self.whenSliderYChanged labels = Hashtable(3) labels.put(-self.posMinMax, JLabel("Below")) labels.put( 0, JLabel("Centre")) labels.put( self.posMinMax, JLabel("Above")) self.positionZSlider.labelTable = labels self.positionZSlider.minimum = -self.posMinMax self.positionZSlider.maximum = self.posMinMax self.positionZSlider.majorTickSpacing = ticksMajor self.positionZSlider.minorTickSpacing = ticksMinor self.positionZSlider.paintTicks = True self.positionZSlider.paintLabels = True self.positionZSlider.snapToTicks = True self.positionZSlider.value = 0 self.positionZSlider.orientation = JSlider.VERTICAL self.positionZSlider.stateChanged = self.whenSliderZChanged # Setup frame self.title = "Simple JMRI Audio Player" self.contentPane.layout = BoxLayout(self.contentPane, BoxLayout.Y_AXIS) # Add controls to frame - combo & buttons first p = JPanel(FlowLayout(FlowLayout.LEADING)) p.add(self.sourceCombo) p.add(self.refreshButton) p.add(self.playButton) p.add(self.pauseButton) p.add(self.stopButton) #p.add(JLabel("Range")) #p.add(self.rangeSpinner) self.add(p) self.add(Box.createVerticalGlue()) # Now sliders p = JPanel(FlowLayout(FlowLayout.LEADING)) label = JLabel("Y Position") label.UI = VerticalLabelUI() # Default behaviour is anti-clockwise p.add(label) p.add(self.positionYSlider) p2 = JPanel() p2.layout = BoxLayout(p2, BoxLayout.Y_AXIS) p3 = JPanel() p3.add(JLabel("Range")) p3.add(self.rangeSpinner) p2.add(p3) #p2.add(Box.createVerticalGlue()) p3 = JPanel() p3.layout = BoxLayout(p3, BoxLayout.Y_AXIS) label = JLabel("X Position") label.alignmentX = JLabel.CENTER_ALIGNMENT p3.add(label) p3.add(self.positionXSlider) p2.add(p3) p.add(p2) label = JLabel("Z Position") label.UI = VerticalLabelUI() p.add(label) p.add(self.positionZSlider) self.add(p) # Finally pack and show self.pack() self.show() def updateSourcesList(self): # Clear the ComboBox self.sourceCombo.removeAllItems() # Now populate self.sourceCombo.addItem(self.SELECT) # Retrieve system name list of AudioSources for source in audio.getSystemNameList(ord(Audio.SOURCE)): # Due to an API error, which is fixed in JMRI 2.11.1, # we have to do it this way as opposed to the more obvious: # for source in audio.getSystemNameList(Audio.SOURCE): # Add available sources to the list self.sourceCombo.addItem(source) def whenRangeChanged(self, event): # store value & update sliders self.range = self.rangeSpinner.value self.updateSliders() def whenSourceChanged(self, event): # Only do something when an item is selected if event.getStateChange() == ItemEvent.SELECTED: # Stop playing source self.stopSource() if (event.getItem() != self.SELECT): # Set reference to source self.source = audio.provideAudio(event.getItem()) # Enable buttons & update sliders self.enableControls(True) self.updateSliders() else: # Clear reference to source self.source = None # Disable buttons self.enableControls(False) def whenButtonClicked(self, event): # Get the action command command = event.getActionCommand() # Execute appropriate action if self.source != None: if command == self.PLAY: self.pauseButton.actionCommand = self.PAUSE self.pauseButton.text = "Pause" self.playSource() elif command == self.PAUSE: self.pauseButton.actionCommand = self.RESUME self.pauseButton.text = "Resume" self.pauseSource() elif command == self.RESUME: self.pauseButton.actionCommand = self.PAUSE self.pauseButton.text = "Pause" self.resumeSource() elif command == self.STOP: self.pauseButton.actionCommand = self.PAUSE self.pauseButton.text = "Pause" self.stopSource() elif command == self.REFRESH: self.updateSourcesList() else: print "No action defined!" def playSource(self): if self.source != None: self.source.play() def pauseSource(self): if self.source != None: self.source.pause() def resumeSource(self): if self.source != None: self.source.resume() def stopSource(self): if self.source != None: self.source.stop() def whenSliderXChanged(self, event): self.changePosition(self.POSX, (float(self.positionXSlider.value)/self.posMinMax*self.range)) def whenSliderYChanged(self, event): self.changePosition(self.POSY, (float(self.positionYSlider.value)/self.posMinMax*self.range)) def whenSliderZChanged(self, event): self.changePosition(self.POSZ, (float(self.positionZSlider.value)/self.posMinMax*self.range)) def changePosition(self, which, value): if self.source != None: # Get the current position pos = self.source.getPosition() # Determine which axis to alter if which == self.POSX: pos.x = value elif which == self.POSY: pos.y = value elif which == self.POSZ: pos.z = value # Now change the position self.source.position = pos def updateSliders(self): # Get the current position pos = self.source.getPosition() # Update sliders self.positionXSlider.value = int(pos.x * self.posMinMax / self.range) self.positionYSlider.value = int(pos.y * self.posMinMax / self.range) self.positionZSlider.value = int(pos.z * self.posMinMax / self.range) def enableControls(self,enable): self.playButton.enabled = enable self.pauseButton.enabled = enable self.stopButton.enabled = enable self.positionXSlider.enabled = enable self.positionYSlider.enabled = enable self.positionZSlider.enabled = enable self.rangeSpinner.enabled = enable a = AudioPlayerFrame()