001    /**
002     * iFish - An iRiver iHP jukebox database creation tool
003     *
004     * Copyright (C) 2009 Richard "Shred" Körber
005     *   http://ifish.shredzone.org
006     *
007     * This program is free software: you can redistribute it and/or modify
008     * it under the terms of the GNU General Public License as published by
009     * the Free Software Foundation, either version 3 of the License, or
010     * (at your option) any later version.
011     *
012     * This program is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
015     * GNU General Public License for more details.
016     *
017     * You should have received a copy of the GNU General Public License
018     * along with this program.  If not, see <http://www.gnu.org/licenses/>.
019     */
020    package net.shredzone.ifish.actions;
021    
022    import net.shredzone.ifish.*;
023    import net.shredzone.ifish.db.*;
024    import net.shredzone.ifish.gui.*;
025    import net.shredzone.ifish.i18n.L;
026    import net.shredzone.ifish.pool.ImgPool;
027    
028    import java.awt.event.ActionEvent;
029    import java.awt.event.KeyEvent;
030    import java.io.*;
031    import java.util.*;
032    import java.util.prefs.*;
033    
034    import javax.swing.Action;
035    import javax.swing.KeyStroke;
036    
037    /**
038     * Player action: starts, stops and pauses the external player.
039     *
040     * @author  Richard Körber &lt;dev@shredzone.de&gt;
041     * @version $Id: PlayerAction.java 291 2009-04-28 21:29:27Z shred $
042     */
043    public class PlayerAction extends IFishAction implements PreferenceChangeListener {
044      private static final long serialVersionUID = 3544951047966503216L;
045    
046      public final static int PLAY  = 0;
047      public final static int PAUSE = 1;
048      public final static int STOP  = 2;
049      
050      private final static String[] TITLES = new String[] {
051        "action.play", "action.pause", "action.stop"
052      };
053      private final static String[] IMAGES = new String[] {
054        "player_play.png", "player_pause.png", "player_stop.png"
055      };
056      private final static KeyStroke[] KEYSTROKES = new KeyStroke[] {
057        KeyStroke.getKeyStroke( KeyEvent.VK_F5, 0 ),
058        KeyStroke.getKeyStroke( KeyEvent.VK_F6, 0 ),
059        KeyStroke.getKeyStroke( KeyEvent.VK_F7, 0 ),
060      };
061      
062      private final int type;
063      
064      /**
065       * Create a new PlayerAction.
066       *
067       * @param   fish        Related IFishPane
068       * @param   type        Type, one of PLAY, PAUSE or STOP.
069       */
070      public PlayerAction( IFishPane fish, int type ) {
071        super(
072          fish,
073          L.tr( TITLES[type] ),
074          ImgPool.get( IMAGES[type] ),
075          L.tr( TITLES[type]+".tt" ),
076          KEYSTROKES[type]
077        );
078        this.type = type;
079        
080        updateStatus();
081        prefs.getNode().addPreferenceChangeListener( this );
082      }
083      
084      /**
085       * The action implementation itself. Do not call directly.
086       */
087      @Override
088      protected void action() {
089        String cmd = getPlayerCmd();
090        if( cmd!=null ) {
091          Entry[] entries = fish.getSelectedEntries();
092          
093          if( type!=PLAY || (entries!=null && entries.length>0) ) {
094            //--- Split command into parts ---
095            String[] args = cmd.split("\\s");
096      
097            //--- Collect the arguments ---
098            List<String> lArgs = new ArrayList<String>( args.length );
099            
100            //--- Replace {} as placeholder ---
101            for( int ix=0; ix<args.length; ix++ ) {
102              if( args[ix].trim().equals("{}") ) {
103                for( int iy=0; iy<entries.length; iy++) {
104                  File file = entries[iy].getFile();
105                  if( file!=null && file.exists() && file.isFile() ) {
106                    lArgs.add( file.getAbsolutePath() );
107                  }
108                }
109              }else {
110                lArgs.add( args[ix] );
111              }
112            }
113            
114            //--- Convert to string ---
115            args = (String[]) lArgs.toArray( new String[lArgs.size()] );
116            lArgs = null;
117            
118            //--- Execute the command ---
119            try {
120              Runtime runtime = Runtime.getRuntime();
121              runtime.exec( args );
122            }catch( IOException ex ) {
123              ExceptionDialog.show( fish, L.tr("a.player.error"), ex );
124            }
125          }else if( type==PLAY && fish.getPlaylistSource()==null ) {
126            //--- Get db to front ---
127            // if no file was selected
128            fish.getAction( IFishPane.ACTION_TAB_DB ).perform();
129          }
130        }
131      }
132      
133      /**
134       * Updates the enabled state of the action.
135       */
136      protected void updateStatus() {
137        String cmd = getPlayerCmd();
138        setEnabled( cmd!=null ); 
139      }
140      
141      /**
142       * Get the player command used for this action.
143       *
144       * @return    Player command, null if none was configured.
145       */
146      protected String getPlayerCmd() {
147        String cmd = null;
148        switch( type ) {
149          case PLAY:
150            cmd = prefs.getPlayerPlay();
151            break;
152          
153          case PAUSE:
154            cmd = prefs.getPlayerPause();
155            break;
156          
157          case STOP:
158            cmd = prefs.getPlayerStop();
159            break;
160        }
161        if( cmd!=null )
162          cmd = cmd.trim();
163        if( cmd!=null && cmd.equals("") )
164          cmd = null;
165        return cmd;
166      }
167      
168      /**
169       * Internal PreferenceChangeListener implementation, do not use.
170       *
171       * @param   evt       PreferenceChangeEvent
172       */
173      @Override
174      public void preferenceChange( PreferenceChangeEvent evt ) {
175        updateStatus();
176      }
177    
178    }
179