/* * AudioTrackPanorama.java * Eisenkraut * * Copyright (c) 2004-2016 Hanns Holger Rutz. All rights reserved. * * This software is published under the GNU General Public License v3+ * * * For further information, please contact Hanns Holger Rutz at * contact@sciss.de */ package de.sciss.eisenkraut.gui; import java.awt.BorderLayout; import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.util.prefs.BackingStoreException; import java.util.prefs.PreferenceChangeEvent; import java.util.prefs.PreferenceChangeListener; import java.util.prefs.Preferences; import javax.swing.JPopupMenu; import javax.swing.WindowConstants; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; import de.sciss.eisenkraut.io.RoutingConfig; import de.sciss.eisenkraut.session.SessionCollection; import de.sciss.eisenkraut.timeline.AudioTrack; import de.sciss.eisenkraut.util.PrefsUtil; import de.sciss.app.AbstractApplication; import de.sciss.app.AbstractWindow; import de.sciss.app.Application; import de.sciss.gui.CoverGrowBox; import de.sciss.common.AppWindow; import de.sciss.util.Disposable; public class AudioTrackPanorama implements Disposable { private final AudioTrack t; private final ActionListener actionListener; private final SessionCollection.Listener scListener; private final PreferenceChangeListener prefListener; private final Preferences audioPrefs; private final SessionCollection tracks; protected PanoramaPanel pan = null; private AppWindow palette = null; private JPopupMenu popup = null; private boolean listening = false; public AudioTrackPanorama( final AudioTrack t, SessionCollection tracks ) { final Application app = AbstractApplication.getApplication(); audioPrefs = app.getUserPrefs().node( PrefsUtil.NODE_AUDIO ); this.t = t; this.tracks = tracks; actionListener = new ActionListener() { public void actionPerformed( ActionEvent e ) { if( pan != null ) { t.getMap().putValue( AudioTrackPanorama.this, AudioTrack.MAP_KEY_PANAZIMUTH, pan.getAzimuth()); t.getMap().putValue( AudioTrackPanorama.this, AudioTrack.MAP_KEY_PANSPREAD, pan.getSpread()); } } }; scListener = new SessionCollection.Listener() { public void sessionCollectionChanged( SessionCollection.Event e ) { if( e.collectionContains( t ) && (e.getModificationType() == SessionCollection.Event.ACTION_REMOVED) ) { dispose(); } } public void sessionObjectMapChanged( SessionCollection.Event e ) { if( (e.getSource() != AudioTrackPanorama.this) && (pan != null) && e.collectionContains( t ) && (e.setContains( AudioTrack.MAP_KEY_PANAZIMUTH ) || e.setContains( AudioTrack.MAP_KEY_PANSPREAD ))) { setAzimuthAndSpread(); } } public void sessionObjectChanged( SessionCollection.Event e ) { /* empty */ } }; prefListener = new PreferenceChangeListener() { public void preferenceChange( PreferenceChangeEvent e ) { if( e.getKey().equals( PrefsUtil.KEY_OUTPUTCONFIG )) { createPanPan(); } } }; } private void createPalette() { if( palette != null ) return; if( popup != null ) destroyPopup(); final Application app = AbstractApplication.getApplication(); palette = new AppWindow( AbstractWindow.PALETTE ); palette.setTitle( app.getResourceString( "palettePanorama" ) + " : " + t.getName() ); createPanPan(); palette.getContentPane().add( CoverGrowBox.create(), BorderLayout.SOUTH ); palette.setDefaultCloseOperation( WindowConstants.DO_NOTHING_ON_CLOSE ); palette.addListener( new AbstractWindow.Adapter() { public void windowClosing( AbstractWindow.Event e ) { dispose(); } }); palette.init(); } private void createPopup( boolean disposeOnMouseRelease ) { if( popup != null ) return; if( palette != null ) destroyPalette(); popup = new JPopupMenu(); createPanPan(); if( disposeOnMouseRelease ) { pan.addMouseListener( new MouseAdapter() { public void mouseReleased( MouseEvent e ) { dispose(); } }); } popup.addPopupMenuListener( new PopupMenuListener() { public void popupMenuCanceled( PopupMenuEvent e ) { dispose(); } public void popupMenuWillBecomeInvisible( PopupMenuEvent e ) { /* empty */ } public void popupMenuWillBecomeVisible( PopupMenuEvent e ) { /* empty */ } }); } public void showPalette() { createPalette(); startListening(); palette.setVisible(true); palette.toFront(); } public void showPopup(Component invoker, int x, int y, boolean beginDragging) { createPopup(beginDragging); startListening(); popup.show(invoker, x, y); if (beginDragging) pan.beginDragging(); } private void startListening() { if (!listening) { tracks.addListener(scListener); audioPrefs.addPreferenceChangeListener(prefListener); listening = true; } } private void stopListening() { if (listening) { tracks.removeListener(scListener); audioPrefs.removePreferenceChangeListener(prefListener); listening = false; } } public void dispose() { stopListening(); destroyPalette(); destroyPopup(); destroyPanPan(); } private void destroyPalette() { if (palette == null) return; palette.dispose(); palette = null; } private void destroyPopup() { if (popup == null) return; popup.setVisible(false); popup = null; } protected void destroyPanPan() { if (pan == null) return; pan.getParent().remove(pan); pan.removeActionListener(actionListener); pan = null; } protected void createPanPan() { final String cfgName = audioPrefs.get( PrefsUtil.KEY_OUTPUTCONFIG, null ); RoutingConfig oCfg; destroyPanPan(); try { if( cfgName != null && audioPrefs.node( PrefsUtil.NODE_OUTPUTCONFIGS ).nodeExists( cfgName )) { oCfg = new RoutingConfig( audioPrefs.node( PrefsUtil.NODE_OUTPUTCONFIGS ).node( cfgName )); pan = new PanoramaPanel( oCfg.numChannels, oCfg.startAngle ); setAzimuthAndSpread(); pan.addActionListener( actionListener ); if( palette != null ) { palette.getContentPane().add( pan, BorderLayout.CENTER ); palette.revalidate(); } else { popup.add( pan, BorderLayout.CENTER ); popup.revalidate(); } } } catch (BackingStoreException e1) { System.err.println("Create pan:"); e1.printStackTrace(); } } protected void setAzimuthAndSpread() { final double azi, spread; Object o; o = t.getMap().getValue(AudioTrack.MAP_KEY_PANAZIMUTH); if ((o != null) && (o instanceof Number)) { azi = ((Number) o).doubleValue(); } else { azi = pan.getAzimuth(); } o = t.getMap().getValue(AudioTrack.MAP_KEY_PANSPREAD); if ((o != null) && (o instanceof Number)) { spread = ((Number) o).doubleValue(); } else { spread = pan.getSpread(); } pan.setAzimuthAndSpread(azi, spread); } }