001/*
002 *  $URL: svn://warp4:3690/open/trunk/projects/jOggPlayer/ca/bc/webarts/jOggPlayer.java $
003 *  $Revision: 552 $
004 *  $Date: 2012-06-19 19:07:24 -0700 (Tue, 19 Jun 2012) $
005 *  $Author: tgutwin $
006 */
007/*
008 *  jOggPlayer -- GUI Enhanced Pure Java Ogg Vorbis player.
009 *
010 *  Graphical and User enhancements Written by Tom Gutwin - WebARTS Design.
011 *  Copyright (C) 2001-2009 WebARTS Design, North Vancouver Canada
012 *  http://jOggPlayer.webarts.bc.ca
013 *
014 *  This program is free software; you can redistribute it and/or modify
015 *  it under the terms of the GNU General Public License as published by
016 *  the Free Software Foundation; either version 2 of the License, or
017 *  (at your option) any later version.
018 *
019 *  This program is distributed in the hope that it will be useful,
020 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
021 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
022 *  GNU General Public License for more details.
023 *
024 *  You should have received a copy of the GNU General Public License
025 *  along with this program; if not, write to the Free Software
026 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
027 */
028/*
029 *  Original Java Vorbis Ogg Audio/Decoder/Player code Written by:
030 *  2000 ymnk<ymnk@jcraft.com>
031 *  Copyright (C) 2000 ymnk, JCraft,Inc.
032 *  http://www.jcraft.com
033 *
034 *  Many thanks to
035 *  Monty <monty@xiph.org> and
036 *  The XIPHOPHORUS Company http://www.xiph.org/ .
037 *  JOrbis has been based on their awesome works, Vorbis codec and
038 *  JOrbisPlayer depends on JOrbis.
039 *
040 */
041/*
042 *  on with the show
043 */
044package ca.bc.webarts;
045
046import java.applet.Applet;
047
048import java.awt.BorderLayout;
049import java.awt.Color;
050import java.awt.Component;
051import java.awt.Dimension;
052import java.awt.FlowLayout;
053import java.awt.Font;
054import java.awt.Frame;
055import java.awt.Graphics;
056import java.awt.GraphicsEnvironment;
057import java.awt.GridLayout;
058import java.awt.Image;
059import java.awt.Label;
060import java.awt.Panel;
061import java.awt.Rectangle;
062import java.awt.Window;
063
064import java.awt.event.ActionEvent;
065import java.awt.event.ActionListener;
066import java.awt.event.MouseAdapter;
067import java.awt.event.MouseEvent;
068import java.awt.event.MouseListener;
069import java.awt.event.MouseMotionAdapter;
070import java.awt.event.MouseMotionListener;
071import java.awt.event.WindowAdapter;
072import java.awt.event.WindowEvent;
073import java.awt.event.WindowListener;
074
075import java.io.File;
076import java.io.FileInputStream;
077import java.io.FileNotFoundException;
078import java.io.InputStream;
079import java.io.IOException;
080
081import java.net.Authenticator;
082import java.net.MalformedURLException;
083import java.net.URL;
084import java.net.URLConnection;
085
086import java.util.Date;
087import java.util.Enumeration;
088import java.util.HashMap;
089import java.util.Vector;
090
091import java.util.jar.JarEntry;
092import java.util.jar.JarFile;
093import java.util.Properties;
094
095import javax.sound.sampled.AudioFileFormat;
096import javax.sound.sampled.AudioFormat;
097import javax.sound.sampled.AudioSystem;
098import javax.sound.sampled.Control;
099import javax.sound.sampled.DataLine;
100import javax.sound.sampled.Line;
101import javax.sound.sampled.LineUnavailableException;
102import javax.sound.sampled.Mixer;
103import javax.sound.sampled.SourceDataLine;
104
105import javax.swing.border.BevelBorder;
106import javax.swing.border.Border;
107import javax.swing.border.EmptyBorder;
108import javax.swing.BorderFactory;
109import javax.swing.BoxLayout;
110import javax.swing.event.ChangeEvent;
111import javax.swing.event.ChangeListener;
112import javax.swing.Icon;
113import javax.swing.ImageIcon;
114import javax.swing.JApplet;
115import javax.swing.JButton;
116import javax.swing.JCheckBox;
117import javax.swing.JColorChooser;
118import javax.swing.JDialog;
119import javax.swing.JEditorPane;
120import javax.swing.JFrame;
121import javax.swing.JMenu;
122import javax.swing.JMenuItem;
123import javax.swing.JOptionPane;
124import javax.swing.JPanel;
125import javax.swing.JPopupMenu;
126import javax.swing.JProgressBar;
127import javax.swing.JScrollPane;
128import javax.swing.JSlider;
129import javax.swing.JWindow;
130import javax.swing.ToolTipManager;
131
132import ca.bc.webarts.tools.Log;
133
134import ca.bc.webarts.widgets.ColouredLabel;
135import ca.bc.webarts.widgets.ExampleFileFilter;
136import ca.bc.webarts.widgets.FirewallAuthenticator;
137import ca.bc.webarts.widgets.JAboutBox;
138import ca.bc.webarts.widgets.JCheckDropDown;
139import ca.bc.webarts.widgets.PlayList;
140import ca.bc.webarts.widgets.Splash;
141import ca.bc.webarts.widgets.Util;
142
143import ca.bc.webarts.widgets.dnd.FileDrop;
144
145import ca.bc.webarts.widgets.dnd.FileDrop.Listener;
146
147//import calpa.html.*;
148
149import com.jcraft.jogg.Packet;
150import com.jcraft.jogg.Page;
151import com.jcraft.jogg.StreamState;
152import com.jcraft.jogg.SyncState;
153
154import com.jcraft.jorbis.Block;
155import com.jcraft.jorbis.Comment;
156import com.jcraft.jorbis.DspState;
157import com.jcraft.jorbis.Info;
158
159import kiwi.ui.KButton;
160import kiwi.ui.KPanel;
161
162import kiwi.util.KiwiUtils;
163
164import org.jconfig.ConfigurationManager;
165
166//NEWlast.fm api using 2.0 API
167//import de.umass.lastfm.Authenticator;
168import de.umass.lastfm.Caller;
169import de.umass.lastfm.Event;
170//import de.umass.lastfm.;
171import de.umass.lastfm.Session;
172import de.umass.lastfm.Track;
173import de.umass.lastfm.User;
174import de.umass.lastfm.scrobble.ResponseStatus;
175import de.umass.lastfm.scrobble.Scrobbler;
176import de.umass.lastfm.scrobble.ScrobbleResult;
177import de.umass.lastfm.scrobble.Source;
178import de.umass.lastfm.PaginatedResult;
179
180/**
181 * An Open Source Platform independant Graphical Vorbis Ogg Player!<P>
182 *
183 * You can now listen to your Oggs using an app that is NOT bloated. In fact this
184 * app/let can run on a web page (it is under 50 kB).<BR clear=left>
185 * <IMG SRC="http://jOggPlayer.webarts.bc.ca/jOggPlayer.png" alt="ScreenShot"><BR>
186 * <P>
187 *
188 * It provides the usual basics needed to enjoy your files:
189 * <UL>
190 *   <LI> plays files from your hard drive or streams from a URL
191 *   <LI> individual file play or multiple file looping play
192 *   <LI> sequential or random play
193 *   <LI> in applet volume control that goes to 11!
194 *   <li> visual song progrees indicator
195 *   <li> displays ogg file information comments ( song name, Artist etc.)
196 *   <li> unlimitted size playlist that can transparently include files and/or
197 *   URLs
198 *   <LI> user selectable directory recursion on file load
199 *   <li> can load a file, URL or a whole directory of files on startup
200 *   <li> PLUS it sounds great!
201 * </UL>
202 * <A HREF="http://www.webarts.bc.ca/jOggPlayer">Visit the Homepage</A> for latest
203 * news and updates. <P>
204 *
205 * Based on the Great work done by the <A HREF="http://www.jcraft.com/jorbis/index.html">
206 * jCraft crew</A> to build jOrbis - the Java implementation of the Vorbis Ogg
207 * Codec by <A HREF="http://www.xiph.org/"> The XIPHOPHORUS Company</A> .<P>
208 *
209 * All the aforementioned work has been released under an OpenSource GNU General
210 * Public License.<BR>
211 * <HR> <P>
212 *
213 * This program is free software; you can redistribute it and/or modify it under
214 * the terms of the GNU General Public License as published by the Free Software
215 * Foundation; either version 2 of the License, or (at your option) any later version.
216 * <P>
217 *
218 * This program is distributed in the hope that it will be useful, but WITHOUT
219 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
220 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
221 * <P>
222 *
223 * You should have received a copy of the GNU General Public License along with
224 * this program; if not, write to the Free Software Foundation, Inc., 675 Mass
225 * Ave, Cambridge, MA 02139, USA.
226 *
227 * @author    Tom Gutwin P.Eng
228 * @created   November 19, 2001
229 */
230public class jOggPlayer extends JApplet
231   implements ActionListener, Runnable
232{
233  // Constants
234  /**
235   * Constant holding the users file seperator. ("/" or "\")
236   */
237  private final static String SYSTEM_FILE_SEPERATOR = File.separator;
238
239  /**
240   * The application name string
241   **/
242  private final static String APP_NAME = "jOggPlayer";
243
244  private final static boolean USE_LASTFM_2 = true;
245
246  /**
247   * A Class holder for its name (used in Logging).
248   **/
249  private static String className_ = APP_NAME;
250  /**
251   * The Log Filename.
252   **/
253  private static String logFile_ = "." + File.separator + className_ + "Log.txt";
254
255  /**
256   * The X amount the current window was just dragged.
257   **/
258  private int XDifference;
259  /** The Y amount the current window was just dragged. **/
260  private int YDifference;
261  /** the x position of the mini window. **/
262  private static int xpos = -1;
263  /** the y position of the mini window. **/
264  private static int ypos = -1;
265  /** the x position of the app window. **/
266  private static int appXpos = -1;
267  /** the y position of the app window. **/
268  private static int appYpos = -1;
269
270  /**
271   * The dir where the images are located.
272   */
273  final static String IMAGE_DIR = "." + SYSTEM_FILE_SEPERATOR +
274    "images" + SYSTEM_FILE_SEPERATOR;
275
276  /**
277   * Class holder for the users dir.
278   */
279  final static String USER_DIR = System.getProperty("user.home") +
280    SYSTEM_FILE_SEPERATOR;
281  /**
282   * Class holder for the classpath.
283   */
284  static String CLASSPATH = System.getProperty("java.class.path");
285  /**
286   * The jOggPlayer persistant config data file.
287   */
288  private static String configFileName_ = USER_DIR+"."+APP_NAME+".xml";
289
290  /**
291   * The version string for this release.
292   */
293  final static String VERSION = _ant.app.version_+" $Revision: 552 $";
294  /**
295   * The Java2 Graphics environment (getrs some platform local data).
296   */
297  final static GraphicsEnvironment USER_GRAPHIC_ENV =
298    GraphicsEnvironment.getLocalGraphicsEnvironment();
299
300  // Variables
301  /**
302   * The codebase dir when running as an application.
303   */
304  static URL appCodeBase_ = null;
305  /**
306   * The codebase dir when running as an applet.
307   */
308  static URL codeBase_ = null;
309  /**
310   * The commandline args that get passed to the app.
311   */
312  static String[] initArgs_ = null;
313  /**
314   * The instantied class.
315   */
316  static jOggPlayer applicationPlayer = null;
317  /**
318   * Description of the Field
319   */
320  static JarFile iconJar = null;
321
322  // Playlist Variables
323  /**
324   * Description of the Field
325   */
326  static String playListDir_ = USER_DIR;
327
328  // Colours
329  /**
330   * The colour used for all panels except the display area.
331   */
332  static Color mainBackColour_ = new Color(100, 180, 245);
333  /**
334   * The colour used to back the display area.
335   */
336  static Color displayBackColour_ = Color.black;
337  /**
338   * The display area text colour.
339   */
340  static Color displayTextColour_ = mainBackColour_.brighter();
341
342  // GUI Componenet Setting Variables
343  /**
344   * The dismiss delay time for the song info Dispay tooltip.
345   */
346   static int songInfoDisplayDismissDelay_ = 8000;
347  /**
348   * Description of the Field
349   */
350  final static int maxVolScale_ = 10;
351  /**
352   * Description of the Field
353   */
354  static int left_vol_scale = maxVolScale_;
355  /**
356   * Description of the Field
357   */
358  static int right_vol_scale = left_vol_scale;
359  /**
360   * Description of the Field
361   */
362  static Dimension frameInitSize_ = null;
363  /**
364   * Description of the Field
365   */
366  static Dimension frameCurrentSize_ = null;
367  /**
368   * Description of the Field
369   */
370  static JCheckBox checkBoxRecursePlaylist =
371    new JCheckBox("Recurse Directories", true);
372  /**
373   * Description of the Field
374   */
375  static JFrame appFrame_ = null;
376  /**
377   * Flag to show the playlist on startup, It gets read from the config file.
378   **/
379  static boolean showPlaylistOnStart_ = true;
380  /**
381   * Flag to specify if the playlist gets auto started on startup.
382   **/
383  static boolean autoPlayOnStart_ = true;
384  /**
385   * Flag to show the mini view on startup, It gets read from the config file.
386   **/
387  static boolean showMiniViewOnStart_  = false;
388  /**
389   * The Volume Slider.
390   */
391  static KButton muteButton_ = new KButton("");
392  /** The last volume before mute.**/
393  static int mutedVolume_ = 0;
394  /**
395   * The Volume Slider.
396   */
397  static JSlider volumeSlider_ = new JSlider(JSlider.VERTICAL,
398    0,
399    maxVolScale_ + 1,
400    maxVolScale_);
401
402  /** Flag to control use of the proxy. **/
403  static private boolean areWeUsingProxy_ = true;
404  /** Flag to control use of the proxy with authentication. **/
405  static private boolean useProxyAuthentication_ = true;
406  /** Username for the proxy authentication. **/
407  static private String proxyUsername_ = "";
408  /** Password for the proxy authentication. **/
409  static private String proxyPassword_ = "";
410  /** Host for the proxy. **/
411  static private String proxyHost_ = "";
412  /** Port for the proxy . **/
413  static private String proxyPort_ = "";
414  /** A list of sites that bypass the proxy. **/
415  static private String proxyNoProxy_ = "";
416
417  static String helpHtmlStr_ =
418          "<HR><U>Installation</U><BR><HR>Installing is easy.<BR> Double click "+
419          "the downloaded jOggPlayer-install.jar file.<BR>"+
420          "OR<BR>Create a new directory" +
421          " and unzip the ZIP archive into it (ie. d:\\apps\\jOggPlayer).<BR>"+
422          "It is now installed.</p><BR>"+
423
424          "<BR><BR><HR><U>Starting jOggPlayer</U><BR><HR>There are a couple of ways to start " +
425          "jOggPlayer<OL><LI>Double click on jOggPlayer.jar. <BR>This works " +
426          "\"out of the box\" with the windoze and Mac OS X Java VMs (UN*X " +
427          "and OS/2 if you have<BR>jar files associated with the java executable).</LI>" +
428          "<LI>Double Click / run one of the included jOggPlayer script files " +
429          "(Un*x Shell jOggPlayer.sh, Windoze<BR>Batch jOggPlayer.bat, Windoze NT " +
430          "Batch jOggPlayer_Winnt.bat, OS/2 jOggPlayer.cmd).<BR>They " +
431          "should run without modifications.These allow the added feature" +
432          " of letting *you* add<BR>commandline parameters; such as specifying " +
433          "some ogg files or URLs to load on startup,<BR>or a directory " +
434          "to search and recurse to load <B>ALL</B> ogg files.</LI>" +
435          "<LI>behind a firewall... use the above script files" +
436          "and add the required information that I have<BR>outlined in the usage " +
437          "below. (email me if you have problems)" +
438          "</LI><LI>directly run it as specified in the usage below.</LI></OL></P>" +
439
440          "<BR><BR><HR><U>Running jOggPlayer</U><BR><HR>The most important thing to remember " +
441          "is that a<BR><B>Right click (Mac: ctrl click) brings up the menu for " +
442          "all features.</B><BR>Most things are straight forward. A few items I " +
443          "should point out:<UL><LI>commandline parameters - you can add " +
444          "filenames, URLs or directory names to load on startup</LI>" +
445          "<LI>jOggPlayer now remembers your last window " +
446          "location,<BR>the view size (mini view or normal view), the background " +
447          "colours</LI>" +
448          "<LI>config items are saved in a XML file called " +
449          "'.jOggPlayer.xml' found<BR>in your user home dir. It is text readable " +
450          "and easy to edit (if you want)</LI>"+
451          "<LI>if you save a playlist file " +
452          "called jOggPlaylist.pls to your user dir,it will auto load it on startup" +
453          "</LI>"+
454          "<LI>Moving the Mini-View... The title area can be clicked and dragged." +
455          "</LI>"+
456          "<LI>Drag &amp; Drop is available... drag &amp; drop an ogg file to "+
457          "the Playlist dropdown box." +
458          "</LI>"+
459          "</UL></P>\n" +
460          "<BR><BR><HR><U>Usage:</U><BR><HR>\n" +
461          "<PRE>\n" +
462          "Usage:\n" +
463          "  java -classpath \"PATH_TO\\jOggPlayer.jar\" ca.bc.webarts.jOggPlayer " +
464          "[file location]\n" +
465          "     OR\n" +
466          "  java -jar .\\jOggPlayer.jar  [file location]\n" +
467          "\n" +
468          "     where [file location] can be:\n" +
469          "                                  a filename\n" +
470          "                                  a URL to a ogg file\n" +
471          "                                  a directory name to recurse " +
472          "for ogg files\n\n" +
473          "If you are behind a firewall and need to get access to files outside \n" +
474          "the proxy you have to set some environment vars before you run the " +
475          "jOggPlayer:\n" +
476          "set proxyHost=myproxy.com\n" +
477          "set proxyPort=8080\n" +
478          "set noProxy=*.webarts.ca\n" +
479          "set proxySet=true\n\n" +
480
481          "OR on the commandline\n" +
482          "Usage:\n" +
483          "java -DproxySet=true -DproxyHost=YourProxyServerHostname \n"+
484          "     -DproxyPort=YourProxyServerPort  \n"+
485          "     -DproxyUser=YourProxyUsernameIFNEEDED  \n"+
486          "     -DproxyPassword=YourProxyUserPasswordIFNEEDED  \n"+
487          "     -DnonProxyHosts=CommaSeperatedlistOfNonProxiedSites  \n"+
488          "     ca.bc.webarts.jOggPlayer [file/URL location]\n"
489          +"</PRE>\n";
490
491  /** The help Text Label html String **/
492  static ColouredLabel helpLabel_ = new ColouredLabel(Color.lightGray,
493                                                       Color.black,
494                                                       helpHtmlStr_);
495
496  /**
497   * The artist Coloured text label.
498   */
499  static ColouredLabel artistLabel = new ColouredLabel(displayBackColour_,
500    displayTextColour_,
501    "Artist: ");
502  /**
503   * Description of the Field
504   */
505  static ColouredLabel titleLabel = new ColouredLabel(displayBackColour_,
506    displayTextColour_,
507    "Song: ");
508  /**
509   * Description of the Field
510   */
511  static ColouredLabel timeLabel = new ColouredLabel(displayBackColour_,
512    displayTextColour_,
513    "Time: ");
514  /**
515   * Description of the Field
516   */
517  static ColouredLabel artistLabelValue = new ColouredLabel(displayBackColour_,
518    displayTextColour_,
519    "None Selected");
520  /**
521   * Description of the Field
522   */
523  static ColouredLabel titleLabelValue = new ColouredLabel(displayBackColour_,
524    displayTextColour_,
525    "None Selected");
526  /**
527   * Description of the Field
528   */
529  static ColouredLabel timeLabelValue = new ColouredLabel(displayBackColour_,
530    displayTextColour_,
531    "00:00");
532  /**
533   * Description of the Field
534   */
535  static ColouredLabel miniTimeLabelValue =
536    new ColouredLabel(displayBackColour_,
537    displayTextColour_,
538    "00:00");
539  /**
540   * Description of the Field
541   */
542  static KPanel headerPanel = new KPanel();
543  /**
544   * Description of the Field
545   */
546  static KPanel bodyPanel = new KPanel();
547  /**
548   * Description of the Field
549   */
550  static KPanel dragableMiniViewPanel = new KPanel();
551  /**
552   * Description of the Field
553   */
554  static KPanel miniViewPanel = new KPanel();
555  /**
556   * Description of the Field
557   */
558  static KPanel miniViewWindowControlPanel = new KPanel();
559  /**
560   * Description of the Field
561   */
562  static KPanel leftPanel = new KPanel();
563  /**
564   * Description of the Field
565   */
566  static KPanel innerPanel = new KPanel();
567  /**
568   * Description of the Field
569   */
570  static KPanel rightPanel = new KPanel();
571  /**
572   * Description of the Field
573   */
574  static KPanel innerHeaderPanel = new KPanel();
575  /**
576   * The panel used to hold all the display components.
577   */
578  static JPanel displayPanel = new JPanel();
579
580  /**
581   * Description of the Field
582   */
583  static KPanel controlPanel = new KPanel();
584  /**
585   * This is where the small buttons and playlist lives.
586   */
587  static KPanel innerFooterPanel = new KPanel();
588  /**
589   * Description of the Field
590   */
591  static JPanel innerDisplayPanel = new JPanel();
592  /**
593   * Description of the Field
594   */
595  static JPanel innerLeftDisplayPanel = new JPanel();
596  /**
597   * Description of the Field
598   */
599  static JPanel innerRightDisplayPanel = new JPanel();
600  /**
601   * Description of the Field
602   */
603  static KPanel innerPlaylistPanel = new KPanel();
604  /**
605   * Description of the Field
606   */
607  static KPanel checkPanel = new KPanel();
608  /**
609   * Description of the Field
610   */
611  static KPanel buttonPanel = new KPanel();
612  /**
613   * Description of the Field
614   */
615  static KPanel miniButtonPanel = new KPanel();
616
617  /**
618   * Description of the Field
619   */
620  static JPopupMenu mainMenu = new JPopupMenu(APP_NAME + " Main Menu");
621  /**
622   * Description of the Field
623   */
624  static JPopupMenu playlistMenu = new JPopupMenu(APP_NAME + " Playlist Menu");
625  /**
626   * Description of the Field
627   */
628  static JPopupMenu displayMenu = new JPopupMenu(APP_NAME + " Display Area Menu");
629  /**
630   * Popup menu Mouse Listener.
631   */
632  static MouseListener popupListener_ =
633    new MouseAdapter()
634    {
635
636      private void maybeShowPopup(MouseEvent e)
637      {
638        if (e.isPopupTrigger())
639        {
640          mainMenu.show(e.getComponent(), e.getX(), e.getY());
641        }
642      }
643
644
645      public void mousePressed(MouseEvent e)
646      {
647        maybeShowPopup(e);
648      }
649
650
651      public void mouseReleased(MouseEvent e)
652      {
653        maybeShowPopup(e);
654      }
655    };
656  /**
657   * The File Load Play Buffer.
658   */
659  static int bufferMultiple_ = 4;
660  /**
661   * The File Load Play Buffer.
662   */
663  static int bufferSize_ = bufferMultiple_ * 256 * 2;
664  /**
665   * Description of the Field
666   */
667  static int convsize = bufferSize_ * 2;
668  /**
669   * Description of the Field
670   */
671  static byte[] convbuffer = new byte[convsize];
672  // Flags
673  /**
674   * Description of the Field
675   */
676  static boolean running_as_applet = true;
677  /**
678   * Description of the Field
679   */
680  boolean playListShowing_ = false;
681  /**
682   * Description of the Field
683   */
684  static boolean miniViewShowing_ = false;
685  /**
686   * flag to control the players thread.  When this goes false this classes run method/thread ends.
687   */
688  boolean playing_ = false;
689  /**
690   * Description of the Field
691   */
692  boolean loopPaused_ = false;
693  /**
694   * Description of the Field
695   */
696  boolean timerRunning_ = false;
697  /**
698   * Description of the Field
699   */
700  boolean logVolumeScale_ = true;
701  /**
702   * Description of the Field
703   */
704  boolean showButtonBorders_ = false;
705  /**
706   * Description of the Field
707   */
708  boolean showTextures_ = false;
709  /**
710   * Small flag when a songs are looping.
711   */
712  boolean looping_ = false;
713
714  //Class Threads
715  /**
716   * Description of the Field
717   */
718  Thread playerThread_ = null;
719  /**
720   * Description of the Field
721   */
722  Thread looperThread_ = null;
723  /**
724   * Description of the Field
725   */
726  double currentVolumeMultiplier_ = 1.0;
727  /**
728   * Description of the Field
729   */
730  long songStartTime_ = 0l;
731  /**
732   * Description of the Field
733   */
734  Date date = new Date();
735  /**
736   * Description of the Field
737   */
738  int progressCount_ = 0;
739  /**
740   * Description of the Field
741   */
742  String playListFilename_ = "file:///"+playListDir_ + "jOggPlaylist.pls";
743  /**
744   * Description of the Field
745   */
746  PlayList playList = null;
747  /**
748   * Description of the Field
749   */
750  Color playlistBackColour_ = new Color(190, 215, 235);
751  /**
752   * Description of the Field
753   */
754  Color buttonBackColour_ = mainBackColour_;
755  /**
756   * Description of the Field
757   */
758  Color volumeBackColour_ = new Color(224, 224, 255);
759  /**
760   *The default font size for all UI controls
761   */
762  int uiFontSize_ = 9;
763  /**
764   * Description of the Field
765   */
766  private static final String[] DEFAULT_TEXTURE_NAMES = {"aquaMarble.gif",
767    "bluesatin.jpg",
768    "brownBricks.gif",
769    "greenMarble.jpg"};
770
771  /**
772   * Description of the Field
773   */
774  String[] availableTextureNames_ = DEFAULT_TEXTURE_NAMES;
775
776  //Fonts
777  /**
778   * Description of the Field
779   */
780  Font displayFont_ = new Font("default", Font.PLAIN, 10);
781  /**
782   * Description of the Field
783   */
784  Font displayFontBold_ = new Font("default", Font.BOLD, 10);
785  /**
786   * Description of the Field
787   */
788  int currVolSetting_ = maxVolScale_;
789  /**
790   * Description of the Field
791   */
792  int playlistHeight_ = 55;
793  /**
794   * Description of the Field
795   */
796  int innerLeftDisplayPanelHeight_ = 52;
797  /**
798   * Description of the Field
799   */
800  int innerLeftDisplayPanelWidth_ = 45;
801  /**
802   * Description of the Field
803   */
804  int innerRightDisplayPanelHeight_ = innerLeftDisplayPanelHeight_;
805  /**
806   * Description of the Field
807   */
808  int innerDisplayPanelHeight_ = innerLeftDisplayPanelHeight_;
809  /**
810   * Description of the Field
811   */
812  int innerDisplayPanelWidth_ = 240;
813  /**
814   * Description of the Field
815   */
816  int songProgressHeight_ = 8;
817  /**
818   * Description of the Field
819   */
820  int controlHeight_ = 64;
821  /**
822   * Description of the Field
823   */
824  int volumeWidth_ = 45;
825  /**
826   * Description of the Field
827   */
828  int displayHeight_ = innerDisplayPanelHeight_ + songProgressHeight_;
829  /**
830   * Description of the Field
831   */
832  int displayWidth_ = innerDisplayPanelWidth_;
833
834  // Gui Components
835  /**
836   * Description of the Field
837   */
838  Image aboutGraphic_ = null;
839  /**
840   * Description of the Field
841   */
842  Image backgroundTexture_ = null;
843  /**
844   * Description of the Field
845   */
846  ImageIcon iconLoveTrack_ = new ImageIcon();
847  ImageIcon iconMiniView_ = new ImageIcon();
848  /**
849   * Description of the Field
850   */
851  ImageIcon iconMiniClose_ = new ImageIcon();
852  /**
853   * Description of the Field
854   */
855  ImageIcon iconDelete_ = new ImageIcon();
856  /**
857   * Description of the Field
858   */
859  ImageIcon iconAdd_ = new ImageIcon();
860  /**
861   * Description of the Field
862   */
863  ImageIcon iconAddUrl_ = new ImageIcon();
864  /**
865   * Description of the Field
866   */
867  ImageIcon iconRefresh_ = new ImageIcon();
868  /**
869   * Description of the Field
870   */
871  ImageIcon iconPlay_ = new ImageIcon();
872  /**
873   * Description of the Field
874   */
875  ImageIcon iconPause_ = new ImageIcon();
876  /**
877   * Description of the Field
878   */
879  ImageIcon iconStop_ = new ImageIcon();
880  /**
881   * Description of the Field
882   */
883  ImageIcon iconForward_ = new ImageIcon();
884  /**
885   * Description of the Field
886   */
887  ImageIcon iconBack_ = new ImageIcon();
888  /**
889   * Description of the Field
890   */
891  ImageIcon iconMiniPlay_ = new ImageIcon();
892  /**
893   * Description of the Field
894   */
895  ImageIcon iconMiniPause_ = new ImageIcon();
896  /**
897   * Description of the Field
898   */
899  ImageIcon iconMiniStop_ = new ImageIcon();
900  /**
901   * Description of the Field
902   */
903  ImageIcon iconMiniForward_ = new ImageIcon();
904  /**
905   * Icon For going back a song.
906   */
907  ImageIcon iconMiniBack_ = new ImageIcon();
908  /**
909   * Unmuted Icon
910   */
911  ImageIcon iconVolOn_ = new ImageIcon();
912  /**
913   * Muted Icon
914   */
915  ImageIcon iconVolOff_ = new ImageIcon();
916  /**
917   * Description of the Field
918   */
919  ImageIcon iconLoop_ = new ImageIcon();
920  /**
921   * Description of the Field
922   */
923  ImageIcon iconSelectedLoop = new ImageIcon();
924  /**
925   * Description of the Field
926   */
927  String backgroundTextureFilename_ = "/images/textures/blueVelvet.jpg";
928  /**
929   * This is the main panel that lives inside the content pane. All others live inside this.
930   */
931  KPanel panel = new KPanel();
932  /**
933   * Description of the Field
934   */
935  KButton miniDragButton = new KButton("");
936  /**
937   * Description of the Field
938   */
939  ColouredLabel miniDragLabel = new ColouredLabel(
940    displayBackColour_,
941    displayTextColour_,
942    new Font("Arial", Font.PLAIN, 9),
943    "jOggPlayer MiniView");
944  /**
945   * Description of the Field
946   */
947  KButton buttonLoveLastfmTrack = new KButton("");
948  /**
949   * Description of the Field
950   */
951  KButton buttonDeleteFromPlaylist = new KButton("");
952  /**
953   * Description of the Field
954   */
955  KButton buttonAddToPlaylist = new KButton("");
956  /**
957   * Description of the Field
958   */
959  KButton buttonAddUrlToPlaylist = new KButton("");
960  /**
961   * Description of the Field
962   */
963  KButton buttonRefreshPlaylist = new KButton("");
964  /**
965   * Description of the Field
966   */
967  KButton button = new KButton("");
968  /**
969   * Description of the Field
970   */
971  KButton buttonPause = new KButton("");
972  /**
973   * Description of the Field
974   */
975  KButton buttonLast = new KButton("");
976  /**
977   * Description of the Field
978   */
979  KButton buttonNext = new KButton("");
980  /**
981   * Description of the Field
982   */
983  KButton miniButtonPlay = new KButton("");
984  /**
985   * Description of the Field
986   */
987  KButton miniButtonPause = new KButton("");
988  /**
989   * Description of the Field
990   */
991  KButton miniButtonLast = new KButton("");
992  /**
993   * Description of the Field
994   */
995  KButton miniButtonNext = new KButton("");
996  /**
997   * Description of the Field
998   */
999  KButton miniButtonView_ = new KButton("");
1000  /**
1001   * Description of the Field
1002   */
1003  KButton miniButtonClose_ = new KButton("");
1004  /**
1005   * Description of the Field
1006   */
1007  JCheckBox checkBoxLoop = new JCheckBox("Loop");
1008  /**
1009   * Description of the Field
1010   */
1011  JCheckBox checkBoxRandom = new JCheckBox("Shuffle", true);
1012  /**
1013   * Description of the Field
1014   */
1015  JCheckBox checkBoxPlaylist = new JCheckBox("Playlist", false);
1016  /**
1017   * Description of the Field
1018   */
1019  JCheckBox checkBoxMiniView = new JCheckBox("Mini", false);
1020  /**
1021   * Description of the Field
1022   */
1023  JProgressBar songProgress = new JProgressBar();
1024
1025  // Ogg File Variables
1026  /**
1027   * Description of the Field
1028   */
1029  InputStream oggBitStream_ = null;
1030  /**
1031   * Description of the Field
1032   */
1033  byte[] buffer = null;
1034  /**
1035   * Description of the Field
1036   */
1037  int bytes = 0;
1038  /**
1039   * Description of the Field
1040   */
1041  int rate = 0;
1042  /**
1043   * Description of the Field
1044   */
1045  int channels = 0;
1046  /**
1047   * The sound output data line.
1048   */
1049  SourceDataLine outputLine = null;
1050  /**
1051   * Description of the Field
1052   */
1053  Vector songComments_ = new Vector();
1054
1055  /** Last.FM Scrobbler Object **/
1056  private static String lastFM_key = "93df6c849563eef04d7d48db5950d0c7";
1057  private static String lastFM_secret = "aa622b7756440145b4405001305b9112";
1058  private static String lastFM_token = null; //de.umass.lastfm.Authenticator.getToken(lastFM_key);
1059  //private static Session lastFM_Session = de.umass.lastfm.Authenticator.getSession(
1060  //                             lastFM_token, lastFM_key, lastFM_secret);
1061  private static Session lastFM_Session = null;
1062  private static String lastFM_SessionKey = "";
1063
1064  String lastFM_userId = "tgutwin";
1065  String lastFM_userPass = "~19AcrobatiC19~~~";
1066  Date lastFM_songStartTime_ = null;
1067  ScrobbleResult scrobbleResult_ =  null ;
1068  ResponseStatus resp_ = null ;
1069  boolean lastFMConnected_  = false;
1070  Session lastFMSession_ = null;
1071  Scrobbler sc_ = null ;
1072
1073  /**
1074   * Listener For the select all as favourite Songs menuitem. *
1075   */
1076  ActionListener selectAllAsFavouriteSongActionListener =
1077    new ActionListener()
1078    {
1079      public void actionPerformed(ActionEvent e)
1080      {
1081        playListComboBox.checkAllItems(true);
1082        playList.selectAllSongs();
1083      }
1084    };
1085
1086  /**
1087   * Listener For the select all as favourite Songs menuitem. *
1088   */
1089  ActionListener deselectAllAsFavouriteSongActionListener =
1090    new ActionListener()
1091    {
1092      public void actionPerformed(ActionEvent e)
1093      {
1094        playListComboBox.checkAllItems(false);
1095        playList.deSelectAllSongs();
1096      }
1097    };
1098
1099  /**
1100   * This Listener gets the first event when the mini view title bar is
1101   * pressed so it can remember the original location of mini window.
1102   * This is in anticipation of a window drag
1103   *
1104   */
1105  MouseAdapter miniViewMouseListener =
1106    new MouseAdapter()
1107    {
1108      /**
1109       * Description of the Method
1110       *
1111       * @param e  Description of Parameter
1112       * @since
1113       */
1114      public void mousePressed(MouseEvent e)
1115      {
1116        XDifference = e.getX();
1117        YDifference = e.getY();
1118      }
1119    };
1120
1121  /**
1122   * This Listener watches/listens where the mini window is being dragged to
1123   * so it can be repainted on the screen because the miniwindow does NOT
1124   * have a Java created titlebar so I have to mimic the window move.
1125   *
1126   */
1127  MouseMotionAdapter dragMiniViewMotionListener =
1128    new MouseMotionAdapter()
1129    {
1130      /**
1131       * Handles a Mouse drag
1132       *
1133       * @param e  Description of Parameter
1134       * @since
1135       */
1136      public void mouseDragged(MouseEvent e)
1137      {
1138        popUpWin_.setLocation(xpos + (e.getX() - XDifference),
1139          ypos + (e.getY() - YDifference));
1140        xpos = xpos + (e.getX() - XDifference);
1141        ypos = ypos + (e.getY() - YDifference);
1142      }
1143    };
1144
1145  /**
1146   * Listener For the Delete Selected Song Playlist Button. *
1147   */
1148  ActionListener deleteSelectedSongActionListener =
1149    new ActionListener()
1150    {
1151      public void actionPerformed(ActionEvent e)
1152      {
1153        //System.out.println("Into Delete From Playlist Action");
1154        String selection =
1155          (String) ((JCheckBox) playListComboBox.getSelectedItem()).getText();
1156        int sel = playListComboBox.getSelectedIndex();
1157        if (playList.removeSong(selection))
1158        {
1159          try
1160          {
1161            playListComboBox.removeItem(selection);
1162          }
1163          catch (Exception ex)
1164          {
1165            log_.major("Exception Thrown: Delete from PlayList FAILED:" +
1166              selection, ex);
1167          }
1168        }
1169        else
1170        {
1171          log_.minor("Delete from PlayList FAILED:" + selection);
1172        }
1173
1174        //now set the index to the song following the one deleted
1175        // which now has the same index number
1176        if (sel < playListComboBox.getNumItems())
1177          playListComboBox.setSelectedIndex(sel);
1178        else
1179          playListComboBox.setSelectedIndex(0);
1180        //playListComboBox.setText(playListComboBox.getSelectedItemName());
1181
1182        playListComboBox.validate();
1183      }
1184    };
1185
1186  /**
1187   * Listener For the Save Favourites to a file Button. *
1188   */
1189  ActionListener saveFavouritesActionListener =
1190    new ActionListener()
1191    {
1192      public void actionPerformed(ActionEvent e)
1193      {
1194        //System.out.println("IntoSave Favourites Action");
1195        ExampleFileFilter filter[] = {new ExampleFileFilter(),
1196          new ExampleFileFilter()};
1197        filter[0].addExtension("pls");
1198        filter[0].setDescription("Playlist Files");
1199        filter[1].addExtension("m3u");
1200        filter[1].setDescription("Winamp Playlist Files");
1201
1202        String tempName = Util.chooseAFilename((Component) e.getSource(),
1203          playListDir_, filter, true, Util.SAVE_DIALOG);
1204        if (tempName != null && tempName != "")
1205        {
1206          /* 1st transfer the jComboBox Selected items to the Playlist */
1207          /* because the Playlist takkes care of the saving */
1208          playList.deSelectAllSongs();
1209          for (int nextIndex= 0; nextIndex < playList.size(); nextIndex++)
1210          {
1211            if (playListComboBox.isItemChecked(nextIndex))
1212              playList.selectSong(nextIndex,true);
1213          }
1214
1215          playListFilename_ = tempName;
1216          playList.saveFavourites(playListFilename_);
1217        }
1218      }
1219    };
1220
1221  /**
1222   * Listener For the Save Playlist to a file Button. *
1223   */
1224  ActionListener savePlaylistActionListener =
1225    new ActionListener()
1226    {
1227      public void actionPerformed(ActionEvent e)
1228      {
1229        //System.out.println("IntoSave Playlist Action");
1230        ExampleFileFilter filter[] = {new ExampleFileFilter(),
1231          new ExampleFileFilter()};
1232        filter[0].addExtension("pls");
1233        filter[0].setDescription("Playlist Files");
1234        filter[1].addExtension("m3u");
1235        filter[1].setDescription("Winamp Playlist Files");
1236
1237        String tempName = Util.chooseAFilename((Component) e.getSource(),
1238          playListDir_, filter, true, Util.SAVE_DIALOG);
1239        if (tempName != null && tempName != "")
1240        {
1241          playListFilename_ = tempName;
1242          playList.savePlaylistFile(playListFilename_);
1243        }
1244      }
1245    };
1246
1247  /**
1248   * Listener For the sorting the playlist by filename. *
1249   **/
1250  ActionListener sortByFilenameActionListener =
1251      new ActionListener()
1252      {
1253        public void actionPerformed(ActionEvent e)
1254        {
1255          System.out.println("Into SortByFilename Playlist Action");
1256          //String[] playListFileNames = PlayList.getPlaylistArray(initArgs_);
1257          //playList = new PlayList(Util.getFileBaseURLs(playListFileNames));
1258          playList.sortSongsByFilename();
1259          playListComboBox.removeAllItems();
1260          String[] playListNames = playList.getSongFileNames();
1261          //System.out.println("Recreating Combobox items-"+playListNames.length);
1262          JCheckBox jc = null;
1263          for (int i = 0; i < playListNames.length; i++)
1264          {
1265            jc = new JCheckBox(playListNames[i], true);
1266            jc.setToolTipText(getSongCommentPopup(i));
1267            playListComboBox.addItem(jc);
1268          }
1269          playListComboBox.validate();
1270        }
1271      };
1272
1273  /**
1274   * Listener For the sorting the playlist by filename. *
1275   **/
1276  ActionListener sortByAlbumActionListener =
1277      new ActionListener()
1278      {
1279        public void actionPerformed(ActionEvent e)
1280        {
1281          System.out.println("Into SortByAlbum Playlist Action");
1282          //String[] playListFileNames = PlayList.getPlaylistArray(initArgs_);
1283          //playList = new PlayList(Util.getFileBaseURLs(playListFileNames));
1284          playList.sortSongsByArtistAlbumTrackNum(); // this sorts with the trackNum Hash
1285          //playList.sortSongsByArtistAlbumTrackTitle();  // this sorts with the trackTitlem Hash
1286          playListComboBox.removeAllItems();
1287          String[] playListNames = playList.getSongFileNames();
1288          //System.out.println("Recreating Combobox items-"+playListNames.length);
1289          JCheckBox jc = null;
1290          for (int i = 0; i < playListNames.length; i++)
1291          {
1292            jc = new JCheckBox(playListNames[i], true);
1293            jc.setToolTipText(getSongCommentPopup(i));
1294            playListComboBox.addItem(jc);
1295          }
1296          playListComboBox.validate();
1297        }
1298      };
1299
1300    /**
1301   * Listener For the Delete ALL Songs from the Playlist Button. *
1302   */
1303  ActionListener deleteAllActionListener =
1304    new ActionListener()
1305    {
1306      public void actionPerformed(ActionEvent e)
1307      {
1308        //System.out.println("Into Delete ALL From Playlist Action");
1309        playList = new PlayList();
1310        playListComboBox.removeAllItems();
1311        playListComboBox.setText("Empty Playlist");
1312        playListComboBox.validate();
1313      }
1314    };
1315
1316  /**
1317   * Listener For the Add a Song to the Playlist Button. *
1318   */
1319  ActionListener addSongActionListener =
1320    new ActionListener()
1321    {
1322      public void actionPerformed(ActionEvent e)
1323      {
1324        //System.out.println("Into Add To Playlist Action");
1325        ExampleFileFilter filter[] = {new ExampleFileFilter()};
1326        filter[0].addExtension("ogg");
1327        filter[0].setDescription("Ogg Song Files");
1328
1329        Vector newFiles = playList.getPlaylistVector(
1330          Util.chooseAFilename((Component) e.getSource(), playListDir_,
1331          filter, true));
1332        String tempEntry = "";
1333        String s = "";
1334        for (int i = 0; i < newFiles.size(); i++)
1335        {
1336          tempEntry = (String) newFiles.get(i);
1337          if (!playList.contains(tempEntry))
1338          {
1339            // Add it to our playlist Object
1340            s = playList.addSong(Util.getFileBaseURL(tempEntry));
1341
1342            // Now add it to the gui component
1343            JCheckBox chBox = new JCheckBox(s, true);
1344            playListComboBox.addItem(chBox);
1345          }
1346        }
1347        // get the index of the 1st added songname
1348        if (newFiles.size() >0)
1349        {
1350          int sel = playListComboBox.getJCheckBoxIndex(
1351            (String) newFiles.get(0));
1352
1353          // Mark it as selected & update the main box
1354          playListComboBox.setSelectedIndex(sel);
1355        }
1356        //playListComboBox.setText(s);
1357        playList.sortSongs();
1358        playListComboBox.removeAllItems();
1359        String[] playListNames = playList.getSongFileNames();
1360        //System.out.println("Recreating Combobox items-"+playListNames.length);
1361        JCheckBox jc = null;
1362        for (int i = 0; i < playListNames.length; i++)
1363        {
1364          jc = new JCheckBox(playListNames[i], true);
1365          jc.setToolTipText(getSongCommentPopup(i));
1366          playListComboBox.addItem(jc);
1367        }
1368        playListComboBox.validate();
1369      }
1370    };
1371
1372  /**
1373   * Listener For the add ALL Songs from PlaylistFile Button. *
1374   */
1375  ActionListener addFromPlaylistActionListener =
1376    new ActionListener()
1377    {
1378      public void actionPerformed(ActionEvent e)
1379      {
1380        //System.out.println("Into Add From Playlist Action");
1381        ExampleFileFilter filter[] = {new ExampleFileFilter(),
1382          new ExampleFileFilter()};
1383        filter[0].addExtension("pls");
1384        filter[0].setDescription("Playlist Files");
1385        filter[1].addExtension("m3u");
1386        filter[1].setDescription("Winamp Playlist Files");
1387
1388        String tempName = Util.chooseAFilename((Component) e.getSource(),
1389          playListDir_, filter, true);
1390        if (tempName != null && tempName != "")
1391        {
1392          URL playlistURL = null;
1393          playListFilename_ = tempName;
1394          if (running_as_applet)
1395          {
1396            try
1397            {
1398              playlistURL = new URL(getCodeBase(), playListFilename_);
1399            }
1400            catch (MalformedURLException ee)
1401            {
1402              System.out.println("The Playlist Filename has some errors. " +
1403                "Please check the filename:\n" + playListFilename_);
1404            }
1405          }
1406          else
1407          {
1408            System.out.println("Opening playlist File" +
1409              playListFilename_);
1410            playlistURL = Util.getFileBaseURL(playListFilename_);
1411          }
1412          playList.loadPlaylist(playlistURL);
1413          playList.sortSongs();
1414          playListComboBox.removeAllItems();
1415          String[] playListNames = playList.getSongFileNames();
1416          JCheckBox jc = null;
1417          for (int i = 0; i < playListNames.length; i++)
1418          {
1419            jc = new JCheckBox(playListNames[i], true);
1420            jc.setToolTipText(getSongCommentPopup(i));
1421            playListComboBox.addItem(jc);
1422          }
1423
1424          // get the index of the 1st added songname
1425          if (playListNames.length >0)
1426          {
1427            int sel = playListComboBox.getJCheckBoxIndex(
1428              playListNames[0]);
1429
1430            // Mark it as selected & update the main box
1431            playListComboBox.setSelectedIndex(sel);
1432          }
1433          //playListComboBox.setText(s);
1434          playListComboBox.validate();
1435        }
1436      }
1437    };
1438
1439  /**
1440   * Listener For the Add a Song from a URL Button. *
1441   */
1442  ActionListener addURLActionListener =
1443    new ActionListener()
1444    {
1445      public void actionPerformed(ActionEvent e)
1446      {
1447        boolean validUrl = false;
1448        boolean cancelled = false;
1449        //System.out.println("Into Add URL To Playlist Action");
1450        String tempEntry = "";
1451
1452        tempEntry = JOptionPane.showInputDialog(getParent(),
1453          new ColouredLabel(Color.lightGray, Color.blue,
1454          "Please Enter the URL to add"),
1455          "Add URL to Playlist",
1456          JOptionPane.QUESTION_MESSAGE);
1457
1458        System.out.println("Adding URL " + tempEntry);
1459        if (tempEntry != null && tempEntry != "")
1460        {
1461          if (tempEntry.endsWith("m3u") || tempEntry.endsWith("pls"))
1462          {
1463            URL playlistURL = null;
1464            try
1465            {
1466              playlistURL = new URL(tempEntry);
1467            }
1468            catch (MalformedURLException ee)
1469            {
1470              System.out.println("The URL cannot be read as a Playlist. " +
1471                "Please check the URL:\n" + tempEntry);
1472            }
1473            playList.loadPlaylist(playlistURL);
1474            playList.sortSongs();
1475            playListComboBox.removeAllItems();
1476            String[] playListNames = playList.getSongFileNames();
1477            JCheckBox jc = null;
1478            for (int i = 0; i < playListNames.length; i++)
1479            {
1480              jc = new JCheckBox(playListNames[i], true);
1481              jc.setToolTipText(getSongCommentPopup(i));
1482              playListComboBox.addItem(jc);
1483            }
1484            // get the index of the 1st added songname
1485            if (playListNames.length >0)
1486            {
1487              int sel = playListComboBox.getJCheckBoxIndex(
1488                playListNames[0]);
1489
1490              // Mark it as selected & update the main box
1491              playListComboBox.setSelectedIndex(sel);
1492            }
1493          }
1494          else
1495          {
1496            URL newUrl = Util.getFileBaseURL(tempEntry);
1497            if (newUrl != null)
1498            {
1499              if (!playList.contains(tempEntry))
1500              {
1501                String s = playList.addSong(Util.getFileBaseURL(tempEntry));
1502                playList.sortSongs();
1503                playListComboBox.removeAllItems();
1504                String[] playListNames = playList.getSongFileNames();
1505                JCheckBox jc = null;
1506                for (int i = 0; i < playListNames.length; i++)
1507                {
1508                  jc = new JCheckBox(playListNames[i], true);
1509                  jc.setToolTipText(getSongCommentPopup(i));
1510                  playListComboBox.addItem(jc);
1511                }
1512
1513                // get the index of the added songname
1514                int sel = playListComboBox.getJCheckBoxIndex(s);
1515
1516                // Mark it as selected & update the main box
1517                playListComboBox.setSelectedIndex(sel);
1518              }
1519              else
1520              {
1521                // get the index of the added songname
1522                int sel = playList.findSong(newUrl);
1523
1524                // Mark it as selected & update the main box
1525                playListComboBox.setSelectedIndex(sel);
1526              }
1527            }
1528          }
1529          playListComboBox.validate();
1530        }
1531      }
1532    };
1533
1534  /**
1535   * Runs the Looping of Songs in its own thread. It simply watches the playerThread_
1536   * to see when it goes null and then increments the currentItemIndex and trys
1537   * to play the next song via tryPlay(...).
1538   */
1539  Runnable loopingRunnable_ =
1540    new Runnable()
1541    {
1542      int watchSleepTime = 1000;
1543
1544      public void run()
1545      {
1546        final int numSongs = playListComboBox.getNumItems();
1547        String item;
1548        looping_ = true;
1549        int currentItemIndex;
1550        while (looping_ &&
1551               numSongs > 0 &&
1552               playListComboBox.getNumItemsChecked() > 0)
1553        {
1554          if (!playing_)
1555          {
1556            //System.out.println("Getting indices for next looped song");
1557            if (checkBoxRandom.isSelected())
1558            {
1559              currentItemIndex = playListComboBox.getRandomCheckedItemNum();
1560            }
1561            else
1562            {
1563              currentItemIndex = playListComboBox.getNextCheckedItemNum();
1564              /*if (currentItemIndex < numSongs-1)
1565              {
1566                currentItemIndex++;
1567              }
1568              else
1569              {
1570                currentItemIndex = 0;
1571              }*/
1572            }
1573            if (currentItemIndex != -1)
1574            {
1575              playListComboBox.setSelectedIndex(currentItemIndex);
1576              item = (String) (((JCheckBox) playListComboBox.getSelectedItem()).getText());
1577              System.out.println("Trying to Play Next Song...");
1578              tryPlay(playList.getURL(item));
1579            }
1580            else
1581              System.out.println("NO Checked Songs to play.");
1582          }
1583          Util.sleep(watchSleepTime);
1584        }
1585      }
1586    };
1587
1588    /**
1589     * The thread that watches the trime the song has been playing.
1590     * Handles the Timer display in its own Thread.<P>
1591     *
1592     * Why not use the Timer class in the JDK??? Because it is since JDK 1.3.
1593     */
1594    class TimerThread extends Thread
1595    {
1596      int min = 0;
1597      int sec = 0;
1598      long pausedTime = 0l;
1599      int pausedMin = 0;
1600      int pausedSec = 0;
1601      Date runningDate;
1602      long runningTime = 0l;
1603      int playTime = 0;
1604      int songDuration = 0;
1605      long startPauseTime = 0l;
1606      long lastPauseTime = 0l;
1607      long newPauseTime = 0l;
1608      long historyPauseTime = 0l;
1609      int diffDate = 0;
1610      String timeString = "00:00";
1611
1612      public int getPlayTime()
1613      {
1614        return playTime;
1615      }
1616
1617      public int getSongDurationInSeconds()
1618      {
1619        //songDuration = songProgress.setMaximum()*((int) (playTime / 1000))/progressCount_;
1620        return songDuration;
1621      }
1622
1623      public void run()
1624      {
1625        date = new Date();
1626        timeLabelValue.setText("00:00");
1627        timeLabelValue.validate();
1628        timerRunning_ = true;
1629        while (playing_ && timerRunning_)
1630        {
1631          Util.sleep(490);
1632          runningDate = new Date();
1633          runningTime = runningDate.getTime();
1634          diffDate = (int) ((runningTime - date.getTime()));
1635          if (loopPaused_)
1636          {
1637            pausedTime = runningTime - startPauseTime;
1638            newPauseTime = runningTime - lastPauseTime;
1639            historyPauseTime += newPauseTime;
1640            pausedMin = (int) historyPauseTime / 60000;
1641            pausedSec = (int) (historyPauseTime / 1000 - pausedMin * 60);
1642
1643            // Flash Tne Paused Message
1644            if (((int) (historyPauseTime / 1000)) % 2 == 0)
1645            {
1646              timeLabelValue.setText(timeString + " (PAUSED)");
1647              miniTimeLabelValue.setText(timeString);
1648              if (miniViewShowing_)
1649              {
1650                miniTimeLabelValue.validate();
1651              }
1652              else
1653              {
1654                timeLabelValue.validate();
1655              }
1656              buttonPause.setBackground(buttonBackColour_.brighter());
1657              buttonPause.validate();
1658            }
1659            else
1660            {
1661              timeLabelValue.setText(timeString);
1662              miniTimeLabelValue.setText(timeString);
1663              if (miniViewShowing_)
1664              {
1665                miniTimeLabelValue.validate();
1666              }
1667              else
1668              {
1669                timeLabelValue.validate();
1670              }
1671              buttonPause.setBackground(buttonBackColour_);
1672              buttonPause.validate();
1673            }
1674            lastPauseTime = runningTime;
1675
1676          }
1677          else
1678          {
1679            playTime = diffDate - (int)historyPauseTime;
1680            min = (int) (playTime / 60000);
1681            sec = ((int) (playTime / 1000)) - min * 60;
1682            songDuration = songProgress.getMaximum()*((int) (playTime / 1000))/progressCount_;
1683            timeString = (min < 9 ? "0" : "") + min + ":" + (sec < 10 ? "0" : "") + sec;
1684            timeLabelValue.setText(timeString + " &nbsp; (" + progressCount_ / 1000 +
1685              "kB)");
1686            miniTimeLabelValue.setText(timeString);
1687            if (miniViewShowing_)
1688            {
1689              miniTimeLabelValue.validate();
1690            }
1691            else
1692            {
1693              timeLabelValue.validate();
1694            }
1695            startPauseTime = runningTime;
1696            lastPauseTime = runningTime;
1697          }
1698        }
1699      }
1700    };
1701    TimerThread timeWatcherThread_ = new TimerThread();
1702
1703  /**
1704   * My own creation - a Dropdown box that can hold checkMarked Items.
1705   */
1706  JCheckDropDown playListComboBox;
1707  /**
1708   * Description of the Field
1709   */
1710  SyncState oggSyncState_;
1711  /**
1712   * Description of the Field
1713   */
1714  StreamState oggStreamState_;
1715  /**
1716   * Description of the Field
1717   */
1718  Page oggPage_;
1719  /**
1720   * Description of the Field
1721   */
1722  Packet oggPacket_;
1723  /**
1724   * Description of the Field
1725   */
1726  Info vorbisInfo;
1727  /**
1728   * Description of the Field
1729   */
1730  Comment vorbisComment;
1731  /**
1732   * Description of the Field
1733   */
1734  DspState vorbisDspState;
1735  /**
1736   * Description of the Field
1737   */
1738  Block vorbisBlock;
1739  /**
1740   * Description of the Field
1741   */
1742  int format;
1743  /**
1744   * Description of the Field
1745   */
1746  int frameSizeInBytes;
1747  /**
1748   * Description of the Field
1749   */
1750  int bufferLengthInBytes;
1751  /**
1752   * The Log that will get used.
1753   */
1754  protected static Log log_ = Log.createLog(Log.MINOR, logFile_);
1755  /**
1756   * The JWindow for the miniView.
1757   */
1758  protected static JWindow popUpWin_ = new JWindow();
1759
1760  private ConfigurationManager cfgmgr_ = ConfigurationManager.getInstance();
1761
1762  /**
1763   * Basic constructor for this Object. It is initated with no songs in the playlist.
1764   */
1765  public jOggPlayer()
1766  {
1767    //    System.out.println("Constructor1");
1768    final String methodName = className_ + ": Constructor()";
1769    log_ = Log.createLog(Log.DEBUG);
1770    log_.startMethod(methodName);
1771
1772     /* register with last.fm  */
1773    handshakeWithLastfm(lastFM_userId,lastFM_userPass);
1774
1775    log_.endMethod();
1776  }
1777
1778
1779  /**
1780   * Constructor for this Object to initated the playlist with the file/songname
1781   * args that are passed to it, if the passed args is empty or values are invalid
1782   * - the default playlistfile is loaded.
1783   *
1784   * @param args  is a set of ogg file names to initially load (it can be a directory
1785   *      name)
1786   */
1787  public jOggPlayer(String[] args)
1788  {
1789    final String methodName = className_ + ": Constructor(String[])";
1790    log_ = Log.createLog(Log.DEBUG);
1791    log_.startMethod(methodName);
1792
1793    initArgs_ = args;
1794    /* register with last.fm  */
1795    handshakeWithLastfm(lastFM_userId,lastFM_userPass);
1796
1797    log_.endMethod();
1798  }
1799
1800
1801  /** Registers and handshakes with last.fm
1802   * @return Scrobbler the registered Scrobbler OR null if failed.
1803  **/
1804  public Scrobbler handshakeWithLastfm(String userId){ return handshakeWithLastfm(userId, lastFM_userPass);}
1805  public Scrobbler handshakeWithLastfm(String userId, String passWd)
1806  {
1807    if(USE_LASTFM_2)
1808    {
1809      System.out.println("Valid LastFM credentials: "+(userId!=null && !userId.equals("")));
1810      if (userId!=null && !userId.equals(""))
1811      {
1812        String lastFM_clientId = "jog"; //"jOggPlayer";
1813        String lastFM_clientVersion = Util.spacesToCapsInString(VERSION);
1814        Caller.getInstance().setUserAgent(lastFM_clientId);
1815        Caller.getInstance().setDebugMode(false);
1816          System.out.println("Getting LastFM Session:");
1817          Session lastFMSession_ = de.umass.lastfm.Authenticator.getMobileSession(userId, passWd, lastFM_key, lastFM_secret);
1818          log_.debug("retrieved lastFMSession_ = "+(lastFMSession_!=null));
1819          if (lastFMSession_!=null)
1820          {
1821            lastFMConnected_ = true;
1822            System.out.println(" SUCCESS.");
1823          }
1824          else
1825            System.out.println(" NOPE.");
1826      }
1827    }
1828    else
1829      sc_ = handshakeWithLastfmOLD(userId);
1830     return sc_;
1831  }
1832
1833  /** Registers and handshakes with last.fm
1834   * @return Scrobbler the registered Scrobbler OR null if failed.
1835  **/
1836  public Scrobbler handshakeWithLastfmOLD(String userId)
1837  {
1838    Scrobbler retVal = null;
1839    if (userId!=null && !userId.equals(""))
1840    {
1841      String lastFM_clientId = "jog"; //"jOggPlayer";
1842      String lastFM_clientVersion = Util.spacesToCapsInString(VERSION);
1843      //ResponseStatus resp = null ;
1844      Caller.getInstance().setUserAgent(lastFM_clientId);
1845      Caller.getInstance().setDebugMode(false);
1846      getLastFMSession();
1847
1848      retVal = Scrobbler.newScrobbler(lastFM_clientId, lastFM_clientVersion,  userId) ;
1849      if (retVal !=null) System.out.println("Scrobbling for Last.fm user "+userId);
1850
1851      /* Handshake with lastfm */
1852      try
1853      {
1854        resp_ = retVal.handshake(lastFM_userPass);
1855        if (resp_ !=null && resp_.ok())
1856        {
1857          lastFMConnected_  = true;
1858          log_.debug("Handshake Succeeded for user: "+userId);
1859          System.out.println("Handshake Succeeded for user: "+userId);
1860        }
1861        else
1862        {
1863          lastFMConnected_  = false;
1864          if (resp_ != null)
1865          {
1866            if (log_!= null)
1867              log_.minor("Handshake Failed for user: "+userId + " - ("+
1868                      getLastfmErrorType(resp_.getStatus()) +") "+resp_.getMessage());
1869              System.out.println("Handshake Failed for user: "+userId + " - ("+
1870                      getLastfmErrorType(resp_.getStatus()) +") "+resp_.getMessage());
1871          }
1872          else
1873          {
1874            if (log_!= null)
1875              log_.minor("Handshake returned a null: "+userId );
1876              System.out.println("Handshake Failed for user: "+userId );
1877          }
1878        }
1879      }
1880      catch (IOException ioEx)
1881      {
1882        if (log_!= null) log_.minor("Error returned from last.fm handshake: ",ioEx);
1883        System.out.println("    Sorry No scrobbling..."+ioEx.getMessage());
1884      }
1885    }
1886
1887    return retVal;
1888  }
1889
1890
1891  /** A small Lookup method to translate the Last.fm ResponseStatus code into a String
1892   * @return string describing the responseCode
1893  **/
1894  public static String getLastfmErrorType(int err)
1895  {
1896    String retVal = "";
1897    switch (err)
1898    {
1899      case ResponseStatus.BADAUTH:
1900        retVal = "BADAUTH";
1901        break;
1902      case ResponseStatus.BADSESSION:
1903        retVal = "BADSESSION";
1904        break;
1905      case ResponseStatus.BADTIME:
1906        retVal = "BADTIME";
1907        break;
1908      case ResponseStatus.BANNED:
1909        retVal = "BANNED";
1910        break;
1911      case ResponseStatus.FAILED:
1912        retVal = "FAILED";
1913        break;
1914      case ResponseStatus.OK:
1915        retVal = "OK";
1916    }
1917    return retVal;
1918  }
1919
1920
1921  /** A small Lookup method to translate the Last.fm ResponseStatus code into a String
1922   * @return string describing the responseCode
1923  **/
1924  public boolean loveLastfmCurrentTrack()
1925  {
1926    boolean retVal = false;
1927    int sel = playListComboBox.getSelectedIndex();
1928    System.out.print("Love Track index:"+sel);
1929    System.out.print( " " +playList.getSongArtist(sel));
1930    System.out.println(" " +playList.getSongTitle(sel));
1931
1932    if (getLastFMSession() != null)
1933    {
1934      de.umass.lastfm.Result result =
1935                    de.umass.lastfm.Track.love( playList.getSongArtist(sel),
1936                                                playList.getSongTitle(sel),
1937                                                getLastFMSession()
1938                                               );
1939      retVal = result.isSuccessful();
1940      System.out.println(" Session Key:"+lastFM_SessionKey);
1941      System.out.println((retVal?"Love It Success":"UnSuccessfull Love"));
1942    }
1943
1944    return retVal;
1945  }
1946
1947
1948  public  Session getLastFMSession()
1949  {
1950    Session retVal = null;
1951
1952    if(USE_LASTFM_2)
1953    {
1954      System.out.println(" lastFMSession_!=null:"+(lastFMSession_!=null));
1955      if(lastFMSession_!=null)
1956      {
1957        retVal = lastFMSession_;
1958      }
1959      else
1960      {
1961        /* register with last.fm  */
1962        System.out.println("Valid LastFM credentials: "+(lastFM_userId!=null && !lastFM_userId.equals("")));
1963        if (lastFM_userId!=null && !lastFM_userId.equals(""))
1964        {
1965          if(USE_LASTFM_2)
1966          {
1967            System.out.println("Getting LastFM Session");
1968            retVal = de.umass.lastfm.Authenticator.getMobileSession(lastFM_userId, lastFM_userPass, lastFM_key, lastFM_secret);
1969            lastFMSession_ = retVal;
1970            lastFM_SessionKey = lastFMSession_.getKey();
1971            log_.debug("retrieved lastFMSession_ = "+(retVal!=null));
1972            if (retVal!=null)
1973            {
1974              lastFMConnected_ = true;
1975              System.out.println("Getting LastFM Session: SUCCESS.");
1976            }
1977            else
1978              System.out.println("Getting LastFM Session: NOPE.");
1979          }
1980          else
1981          {
1982            sc_ = handshakeWithLastfm(lastFM_userId);
1983          }
1984        }
1985      }
1986    }
1987    else
1988      retVal = getLastFMSession(lastFM_token, lastFM_key, lastFM_secret) ;
1989    return retVal;
1990  }
1991
1992
1993  public  Session getLastFMSession(String token, String apiKey, String secret)
1994  {
1995    if (lastFM_Session == null )
1996    {
1997      if (lastFM_SessionKey != null && lastFM_SessionKey.length()>0)
1998      {
1999        // re-create previous session as per http://www.last.fm/api/desktopauth  and
2000        // file:///home/share/dev/lib/last.fm/trunk/doc/de/umass/lastfm/Session.html#createSession(java.lang.String,%20java.lang.String,%20java.lang.String)
2001        lastFM_Session = Session.createSession(lastFM_key, lastFM_secret, lastFM_SessionKey);
2002        System.out.println("existing lastFM_SessionKey = "+lastFM_SessionKey);
2003
2004      }
2005      // create a new one  if it is still NOT available
2006      if (lastFM_Session == null)
2007      {
2008        // create NEW session
2009        //System.out.println("lastFM_token = "+lastFM_token);
2010        //lastFM_token = "d62645a5e45dcff9424ee94b19e6952f";
2011        System.out.println("lastFM_key = "+lastFM_key);
2012        if (lastFM_token == null || lastFM_token.length() == 0)
2013        {
2014          lastFM_token = de.umass.lastfm.Authenticator.getToken(lastFM_key);
2015          System.out.println("NEW lastFM_token = "+lastFM_token);
2016          System.out.println("\n  http://www.last.fm/api/auth/?api_key="+lastFM_key+"&token="+lastFM_token);
2017          System.out.println("\n  Sleeping 2 minutes to authenticate...");
2018          Util.sleep(120000);
2019        }
2020
2021        lastFM_Session = de.umass.lastfm.Authenticator.getSession(lastFM_token, lastFM_key, lastFM_secret);
2022        if (lastFM_Session != null ) lastFM_SessionKey = lastFM_Session.getKey();
2023        if (lastFM_SessionKey != null) System.out.println("NEW lastFM_SessionKey = "+lastFM_SessionKey);
2024        //lastFM_Session = de.umass.lastfm.Authenticator.getMobileSession(
2025        //                                 lastFM_userId, de.umass.util.StringUtilities.md5(lastFM_userPass),
2026        //                                 lastFM_key, lastFM_secret);
2027      }
2028    }
2029    return lastFM_Session;
2030  }
2031
2032
2033  public URL getCodeBase()
2034  {
2035    URL retVal = codeBase_;
2036    if (retVal == null)
2037      retVal = super.getCodeBase();
2038    return retVal;
2039  }
2040
2041
2042  /**
2043   * Sets all the Various colours to their current variable values.
2044   */
2045  private void setColours()
2046  {
2047    final String methodName = className_ + ": setColours()";
2048    log_.startMethod(methodName);
2049    int slight = 25;
2050    int slightlyBrighterRed = (mainBackColour_.getRed() < (256 - slight) ?
2051      mainBackColour_.getRed() + slight :
2052      255);
2053    int slightlyBrighterGreen = (mainBackColour_.getGreen() < (256 - slight) ?
2054      mainBackColour_.getGreen() + slight :
2055      255);
2056    int slightlyBrighterBlue = (mainBackColour_.getBlue() < (256 - slight) ?
2057      mainBackColour_.getBlue() + slight :
2058      255);
2059    displayTextColour_ = new Color(slightlyBrighterRed,
2060      slightlyBrighterGreen,
2061      slightlyBrighterBlue);
2062    playlistBackColour_ = mainBackColour_.brighter();
2063    volumeBackColour_ = displayTextColour_;
2064    buttonBackColour_ = mainBackColour_;
2065    backgroundTexture_ = Util.loadImage(backgroundTextureFilename_);
2066
2067    if (!running_as_applet) appFrame_.setBackground(mainBackColour_);
2068    displayPanel.setBackground(displayBackColour_);
2069    songProgress.setBackground(displayBackColour_);
2070    innerDisplayPanel.setBackground(displayBackColour_);
2071    innerLeftDisplayPanel.setBackground(displayBackColour_);
2072    innerRightDisplayPanel.setBackground(displayBackColour_);
2073    artistLabel.setBackground(displayBackColour_);
2074    artistLabelValue.setBackground(displayBackColour_);
2075    titleLabel.setBackground(displayBackColour_);
2076    titleLabelValue.setBackground(displayBackColour_);
2077    timeLabel.setBackground(displayBackColour_);
2078    timeLabelValue.setBackground(displayBackColour_);
2079    miniTimeLabelValue.setBackground(displayBackColour_);
2080    innerFooterPanel.setBackground(mainBackColour_);
2081    buttonPanel.setBackground(buttonBackColour_);
2082    miniButtonPanel.setBackground(buttonBackColour_);
2083    miniViewWindowControlPanel.setBackground(displayBackColour_);
2084    controlPanel.setBackground(buttonBackColour_);
2085    checkPanel.setBackground(buttonBackColour_);
2086    checkBoxLoop.setBackground(buttonBackColour_);
2087    checkBoxRandom.setBackground(buttonBackColour_);
2088    checkBoxPlaylist.setBackground(buttonBackColour_);
2089    checkBoxMiniView.setBackground(buttonBackColour_);
2090    volumeSlider_.setBackground(volumeBackColour_);
2091    panel.setBackground(buttonBackColour_);
2092    innerPanel.setBackground(buttonBackColour_);
2093    songProgress.setBackground(displayBackColour_);
2094    songProgress.setForeground(mainBackColour_.darker());
2095    innerPlaylistPanel.setBackground(playlistBackColour_);
2096    innerPlaylistPanel.setOpaque(true);
2097    innerPlaylistPanel.setTexture(null);
2098    if (showTextures_)
2099    {
2100      //      buttonPanel.setTexture(backgroundTexture_);
2101      controlPanel.setTexture(backgroundTexture_);
2102      //      checkPanel.setTexture(backgroundTexture_);
2103      buttonPanel.setOpaque(false);
2104      miniButtonPanel.setOpaque(false);
2105      miniViewWindowControlPanel.setOpaque(false);
2106      controlPanel.setOpaque(false);
2107      checkPanel.setOpaque(false);
2108    }
2109    else
2110    {
2111      buttonPanel.setOpaque(true);
2112      miniButtonPanel.setOpaque(true);
2113      controlPanel.setOpaque(true);
2114      checkPanel.setOpaque(true);
2115      buttonPanel.setTexture(null);
2116      miniButtonPanel.setTexture(null);
2117      miniViewWindowControlPanel.setTexture(null);
2118      controlPanel.setTexture(null);
2119      checkPanel.setTexture(null);
2120    }
2121
2122    artistLabel.setTextColour(displayTextColour_);
2123    titleLabel.setTextColour(displayTextColour_);
2124    timeLabel.setTextColour(displayTextColour_);
2125    artistLabelValue.setTextColour(displayTextColour_);
2126    titleLabelValue.setTextColour(displayTextColour_);
2127    timeLabelValue.setTextColour(displayTextColour_);
2128    miniTimeLabelValue.setTextColour(displayTextColour_);
2129    miniDragLabel.setTextColour(displayTextColour_);
2130    artistLabel.setBackColour(displayBackColour_);
2131    titleLabel.setBackColour(displayBackColour_);
2132    timeLabel.setBackColour(displayBackColour_);
2133    artistLabelValue.setBackColour(displayBackColour_);
2134    titleLabelValue.setBackColour(displayBackColour_);
2135    timeLabelValue.setBackColour(displayBackColour_);
2136    miniTimeLabelValue.setBackColour(displayBackColour_);
2137
2138    button.setBorderPainted(showButtonBorders_);
2139    buttonPause.setBorderPainted(showButtonBorders_);
2140    buttonLast.setBorderPainted(showButtonBorders_);
2141    buttonNext.setBorderPainted(showButtonBorders_);
2142    miniButtonPlay.setBorderPainted(showButtonBorders_);
2143    miniButtonPause.setBorderPainted(showButtonBorders_);
2144    miniButtonLast.setBorderPainted(showButtonBorders_);
2145    miniButtonNext.setBorderPainted(showButtonBorders_);
2146
2147    checkBoxRecursePlaylist.setBackground(playlistBackColour_);
2148    buttonDeleteFromPlaylist.setBorderPainted(showButtonBorders_);
2149    buttonAddToPlaylist.setBorderPainted(showButtonBorders_);
2150    buttonAddUrlToPlaylist.setBorderPainted(showButtonBorders_);
2151    buttonLoveLastfmTrack.setBorderPainted(showButtonBorders_);
2152    buttonRefreshPlaylist.setBorderPainted(showButtonBorders_);
2153    log_.endMethod();
2154  }
2155
2156
2157  /**
2158   * Changes all the Labels in the Display area to the ne font. It re validates
2159   * the display as well.
2160   *
2161   * @param newFont  The new DisplayFont value
2162   */
2163  private void setDisplayFont(Font newFont)
2164  {
2165    final String methodName = className_ + ": setDisplayFont(Font)";
2166    log_.startMethod(methodName);
2167    displayFont_ = newFont;
2168    displayFontBold_ = newFont.deriveFont(Font.BOLD);
2169    artistLabel.setFont(newFont);
2170    titleLabel.setFont(newFont);
2171    timeLabel.setFont(newFont);
2172    artistLabelValue.setFont(newFont);
2173    titleLabelValue.setFont(newFont);
2174    timeLabelValue.setFont(newFont);
2175    miniTimeLabelValue.setFont(newFont);
2176    displayPanel.validate();
2177
2178    uiFontSize_=newFont.getSize();
2179    checkBoxLoop.setFont(new Font(checkBoxLoop.getFont().getFontName(),checkBoxLoop.getFont().getStyle(),uiFontSize_));
2180    checkBoxRandom.setFont(new Font(checkBoxRandom.getFont().getFontName(),checkBoxRandom.getFont().getStyle(),uiFontSize_));
2181    checkBoxMiniView.setFont(new Font(checkBoxMiniView.getFont().getFontName(),checkBoxMiniView.getFont().getStyle(),uiFontSize_));
2182    checkBoxPlaylist.setFont(new Font(checkBoxPlaylist.getFont().getFontName(),checkBoxPlaylist.getFont().getStyle(),uiFontSize_));
2183    checkBoxRecursePlaylist.setFont(new Font(checkBoxRecursePlaylist.getFont().getFontName(),checkBoxRecursePlaylist.getFont().getStyle(),uiFontSize_));
2184
2185    checkPanel.validate();
2186    volumeSlider_.validate();
2187    innerPlaylistPanel.validate();
2188    log_.endMethod();
2189  }
2190
2191
2192  /**
2193   * Gets the OutputLine attribute of the jOggPlayer object
2194   *
2195   * @param channels  Description of Parameter
2196   * @param rate      Description of Parameter
2197   * @return          The OutputLine value
2198   */
2199  private SourceDataLine getOutputLine(int channels, int rate)
2200  {
2201    final String methodName = className_ + ": getOutputLine()";
2202    log_.startMethod(methodName);
2203    if (outputLine != null || this.rate != rate || this.channels != channels)
2204    {
2205      if (outputLine != null)
2206      {
2207        try
2208        {
2209          outputLine.drain();
2210        }
2211        catch (NullPointerException outputLineEx)
2212        {
2213          log_.minor("SourceDataLine NullPointerException" ,outputLineEx);
2214        }
2215        try
2216        {
2217          outputLine.stop();
2218        }
2219        catch (Exception outputLineEx)
2220        {
2221          log_.minor("SourceDataLine.stop Exception" ,outputLineEx);
2222        }
2223        try
2224        {
2225          outputLine.close();
2226        }
2227        catch (Exception outputLineEx)
2228        {
2229          log_.minor("SourceDataLine.close Exception" ,outputLineEx);
2230        }
2231      }
2232      init_audio(channels, rate);
2233      outputLine.start();
2234    }
2235    log_.endMethod();
2236
2237    return outputLine;
2238  }
2239
2240
2241  /**
2242   * Loads the names of the textures available in this classes jar file.
2243   *
2244   * @return   an array of strings containing the relative paths of all textures
2245   *      within the jar file.
2246   */
2247  private String[] loadTextureNames()
2248  {
2249    final String methodName = className_ + ": loadTextureNames()";
2250    log_.startMethod(methodName);
2251    String[] retVal = null;
2252    if (running_as_applet)
2253      log_.debug("looking for the jOggPlayer.jar file from the " +
2254      "following classpath:\n" + CLASSPATH);
2255    String defaultJarFileName =
2256      Util.tokenReplace(codeBase_.getFile(),"/",File.separator)+
2257      File.separator+"jOggPlayer.jar";
2258    String jarFileName = null;
2259    if (defaultJarFileName != null && !defaultJarFileName.equals(""))
2260    {
2261      log_.debug("defaultJarName: "+defaultJarFileName);
2262      //System.out.println("defaultJarName: "+defaultJarFileName);
2263      jarFileName = Util.getFilePathFromClasspath("jOggPlayer.jar",
2264        defaultJarFileName);
2265    }
2266    else
2267      jarFileName = Util.getFilePathFromClasspath("jOggPlayer.jar");
2268    String name = null;
2269    try
2270    {
2271      JarFile jar = new JarFile(jarFileName, false);
2272      log_.debug("Jar: "+jarFileName);
2273      //System.out.println("Jar: "+jarFileName);
2274      Vector v = new Vector();
2275      for (Enumeration enumeration = jar.entries(); enumeration.hasMoreElements(); )
2276      {
2277        name = ((JarEntry) enumeration.nextElement()).getName();
2278        //System.out.print(" "+name);
2279        if (name.startsWith("images/textures/"))
2280        {
2281          v.add(name.substring(16));
2282          //System.out.print(".");
2283        }
2284      }
2285      //System.out.print("\n");
2286      Object[] o = v.toArray();
2287      retVal = new String[o.length];
2288      for (int i=0; i<o.length; i++)
2289        retVal[i] = (String)o[i];
2290    }
2291    catch (NullPointerException fEx)
2292    {
2293      log_.major("Jar NullPointerException " + name,fEx);
2294      //System.out.println("Jar NullPointerException " + name);
2295    }
2296    catch (FileNotFoundException fEx)
2297    {
2298      log_.major("Jar FileNotFoundException " + name, fEx);
2299      //System.out.println("Jar FileNotFoundException " + name);
2300    }
2301    catch (IOException ioEx)
2302    {
2303      log_.major("Jar IOException ",ioEx);
2304      //System.out.println("Jar IOException ");
2305    }
2306    catch (SecurityException secEx)
2307    {
2308      log_.major("Jar SecurityException " + name, secEx);
2309      //System.out.println("Jar SecurityException " + name);
2310    }
2311    log_.endMethod();
2312
2313    return retVal;
2314  }
2315
2316
2317  /**
2318   * Loads / initializes the class vars for all required icons and images this
2319   * app/let uses.<P>
2320   *
2321   *
2322   * <UL>
2323   *   <LI> iconDelete_
2324   *   <LI> iconAdd_
2325   *   <LI> iconAddUrl_
2326   *   <LI> iconRefresh_
2327   *   <LI> iconPlay_
2328   *   <LI> iconPause_
2329   *   <LI> iconStop_
2330   *   <LI> iconForward_
2331   *   <LI> iconBack_
2332   *   <LI> iconLoop_
2333   *   <LI> aboutGraphic_
2334   * </UL>
2335   *
2336   */
2337  private void loadIconImages()
2338  {
2339    final String methodName = className_ + ": loadIconImages()";
2340    log_.startMethod(methodName);
2341    String aboutImageFilename = "/images/dont_pan.jpg";
2342    String miniViewFilename = "/images/miniViewButtonImage.jpg";
2343    String miniCloseFilename = "/images/miniCloseButtonImage.jpg";
2344    //String miniCloseFilename = "miniViewButtonImage.jpg";
2345    //String miniViewFilename = "miniViewButtonImage.jpg";
2346    String currImgName = aboutImageFilename;
2347    ImageIcon[] icons = {iconDelete_, iconAdd_, iconAddUrl_, iconRefresh_,
2348      iconPlay_, iconPause_, iconStop_, iconForward_, iconBack_,
2349      iconMiniPlay_, iconMiniPause_, iconMiniStop_,
2350      iconMiniForward_, iconMiniBack_, iconLoop_,
2351      iconSelectedLoop, iconVolOn_, iconVolOff_};
2352    String[] iconFileName = {
2353    /* "/org/javalobby/icons/16x16/DeleteDocument.gif",
2354      "/org/javalobby/icons/16x16/Open.gif",
2355      "/org/javalobby/icons/16x16/New.gif",
2356      "/org/javalobby/icons/16x16/NewFolder.gif",
2357      "/org/javalobby/icons/20x20/VCRPlay.gif",
2358      "/org/javalobby/icons/20x20/VCRPause.gif",
2359      "/org/javalobby/icons/20x20/VCRStop.gif",
2360      "/org/javalobby/icons/20x20/VCRForward.gif",
2361      "/org/javalobby/icons/20x20/VCRBack.gif",
2362      "/org/javalobby/icons/16x16/VCRPlay.gif",
2363      "/org/javalobby/icons/16x16/VCRPause.gif",
2364      "/org/javalobby/icons/16x16/VCRStop.gif",
2365      "/org/javalobby/icons/16x16/VCRForward.gif",
2366      "/org/javalobby/icons/16x16/VCRBack.gif",
2367      "/org/javalobby/icons/20x20/RotCWDown.gif",
2368      "/org/javalobby/icons/20x20/RotCWUp.gif",
2369      "/org/javalobby/icons/20x20/volOn.gif",
2370      "/org/javalobby/icons/20x20/volOff.gif"
2371    */
2372      "/org/javalobby/icons/16x16/DeleteDocument.png",
2373      "/org/javalobby/icons/16x16/Open.png",
2374      "/org/javalobby/icons/16x16/New.png",
2375      "/org/javalobby/icons/16x16/NewFolder.png",
2376      "/org/javalobby/icons/20x20/VCRPlay.png",
2377      "/org/javalobby/icons/20x20/VCRPause.png",
2378      "/org/javalobby/icons/20x20/VCRStop.png",
2379      "/org/javalobby/icons/20x20/VCRForward.png",
2380      "/org/javalobby/icons/20x20/VCRBack.png",
2381      "/org/javalobby/icons/16x16/VCRPlay.png",
2382      "/org/javalobby/icons/16x16/VCRPause.png",
2383      "/org/javalobby/icons/16x16/VCRStop.png",
2384      "/org/javalobby/icons/16x16/VCRForward.png",
2385      "/org/javalobby/icons/16x16/VCRBack.png",
2386      "/org/javalobby/icons/20x20/RotCWDown.png",
2387      "/org/javalobby/icons/20x20/RotCWUp.png",
2388      "/org/javalobby/icons/20x20/volOn.png",
2389      "/org/javalobby/icons/20x20/volOff.png"
2390};
2391    String[] iconDesc = {"Remove", "Add", "Add URL", "Refresh",
2392      "Play", "Pause", "Stop", "Forward", "Back",
2393      "Play", "Pause", "Stop", "Forward", "Back",
2394      "Not Loop", "Looping","Mute","Un-Mute"};
2395
2396    // first get the about box graphic
2397    aboutGraphic_ = Util.loadImage(currImgName);
2398
2399    currImgName = miniCloseFilename;
2400    iconMiniClose_ =
2401      new ImageIcon(Util.loadImage(currImgName), "Close jOggPlayer");
2402
2403    currImgName = miniViewFilename;
2404    iconMiniView_ =
2405      new ImageIcon(Util.loadImage(currImgName), "Toggle Mini View");
2406
2407    iconLoveTrack_ =
2408      new ImageIcon(Util.loadImage("/images/loveLastfmTrack.jpg"), "Love LastFM Track");
2409
2410    ImageIcon tempIcon;
2411    // now get the button image icons
2412    for (int i = 0; i < icons.length; i++)
2413    {
2414      tempIcon =
2415        new ImageIcon(Util.loadImage(iconFileName[i]), iconDesc[i]);
2416      switch (i)
2417      {
2418        case 0:
2419          iconDelete_ = tempIcon;
2420          //new ImageIcon(iconBytes, iconDesc[i]);
2421          break;
2422        case 1:
2423          iconAdd_ = tempIcon;
2424          //new ImageIcon(iconBytes, iconDesc[i]);
2425          break;
2426        case 2:
2427          iconAddUrl_ = tempIcon;
2428          //new ImageIcon(iconBytes, iconDesc[i]);
2429          break;
2430        case 3:
2431          iconRefresh_ = tempIcon;
2432          //new ImageIcon(iconBytes, iconDesc[i]);
2433          break;
2434        case 4:
2435          iconPlay_ = tempIcon;
2436          //new ImageIcon(iconBytes, iconDesc[i]);
2437          break;
2438        case 5:
2439          iconPause_ = tempIcon;
2440          //new ImageIcon(iconBytes, iconDesc[i]);
2441          break;
2442        case 6:
2443          iconStop_ = tempIcon;
2444          //new ImageIcon(iconBytes, iconDesc[i]);
2445          break;
2446        case 7:
2447          iconForward_ = tempIcon;
2448          //new ImageIcon(iconBytes, iconDesc[i]);
2449          break;
2450        case 8:
2451          iconBack_ = tempIcon;
2452          //new ImageIcon(iconBytes, iconDesc[i]);
2453          break;
2454        case 9:
2455          iconMiniPlay_ = tempIcon;
2456          //new ImageIcon(iconBytes, iconDesc[i]);
2457          break;
2458        case 10:
2459          iconMiniPause_ = tempIcon;
2460          //new ImageIcon(iconBytes, iconDesc[i]);
2461          break;
2462        case 11:
2463          iconMiniStop_ = tempIcon;
2464          //new ImageIcon(iconBytes, iconDesc[i]);
2465          break;
2466        case 12:
2467          iconMiniForward_ = tempIcon;
2468          //new ImageIcon(iconBytes, iconDesc[i]);
2469          break;
2470        case 13:
2471          iconMiniBack_ = tempIcon;
2472          //new ImageIcon(iconBytes, iconDesc[i]);
2473          break;
2474        case 14:
2475          iconLoop_ = tempIcon;
2476          //new ImageIcon(iconBytes, iconDesc[i]);
2477          break;
2478        case 15:
2479          iconLoop_ = tempIcon;
2480          //new ImageIcon(iconBytes, iconDesc[i]);
2481          break;
2482        case 16:
2483          iconVolOn_ = tempIcon;
2484          //new ImageIcon(iconBytes, iconDesc[i]);
2485          break;
2486        case 17:
2487          iconVolOff_ = tempIcon;
2488          //new ImageIcon(iconBytes, iconDesc[i]);
2489          break;
2490      }
2491    }
2492
2493    log_.endMethod();
2494  }
2495
2496
2497  /**
2498   * Initializes all the jOrbis and jOgg vars that are used for song playback.
2499   */
2500  private void init_jorbis()
2501  {
2502    final String methodName = className_ + ": init_jorbis()";
2503    log_.startMethod(methodName);
2504    oggSyncState_ = new SyncState();
2505    oggStreamState_ = new StreamState();
2506    oggPage_ = new Page();
2507    oggPacket_ = new Packet();
2508    vorbisInfo = new Info();
2509    vorbisComment = new Comment();
2510    vorbisDspState = new DspState();
2511    vorbisBlock = new Block(vorbisDspState);
2512    buffer = null;
2513    bytes = 0;
2514    oggSyncState_.init();
2515    log_.endMethod();
2516  }
2517
2518
2519  /**
2520   * Initializes the jOggPlayer audio line variables.
2521   *
2522   * @param channels  Description of Parameter
2523   * @param rate      Description of Parameter
2524   */
2525  private void init_audio(int channels, int rate)
2526  {
2527    final String methodName = className_ + ": init_audio()";
2528    log_.startMethod(methodName);
2529    try
2530    {
2531      AudioFormat audioFormat = new AudioFormat((float) rate,
2532        16,
2533        channels,
2534        true,  // PCM_Signed
2535        false // littleEndian
2536      );
2537      DataLine.Info info = new DataLine.Info(SourceDataLine.class,
2538        audioFormat,
2539        AudioSystem.NOT_SPECIFIED);
2540      if (!AudioSystem.isLineSupported(info))
2541      {
2542        System.out.println("Line " + info + " not supported.");
2543        return;
2544      }
2545      try
2546      {
2547        outputLine = (SourceDataLine) AudioSystem.getLine(info);
2548        outputLine.open(audioFormat);
2549      }
2550      catch (LineUnavailableException ex)
2551      {
2552        System.out.println("Unable to open the sourceDataLine: " + ex);
2553        System.out.println("  Type: "+info);
2554        System.out.println("  For: "+outputLine);
2555        System.out.println("  Supported Mixers: ");
2556        Mixer.Info [] mixInfo = AudioSystem.getMixerInfo();
2557        for (int i=0; i< mixInfo.length; i++)
2558        {
2559          System.out.println("    - "+mixInfo[i]);
2560        }
2561        System.out.println("\n  Supported Types: ");
2562        AudioFileFormat.Type [] aTypes = AudioSystem.getAudioFileTypes();
2563        for (int i=0; i< aTypes.length; i++)
2564        {
2565          System.out.println("    - "+aTypes[i]);
2566        }
2567        ex.printStackTrace();
2568        return;
2569      }
2570      catch (IllegalArgumentException ex)
2571      {
2572        System.out.println("Illegal Argument: " + ex);
2573        return;
2574      }
2575      frameSizeInBytes = audioFormat.getFrameSize();
2576      int bufferLengthInFrames = outputLine.getBufferSize() / frameSizeInBytes / 2;
2577      bufferLengthInBytes = bufferLengthInFrames * frameSizeInBytes;
2578      this.rate = rate;
2579      this.channels = channels;
2580
2581      // Now get an equalizer setup
2582      //Control[] outputLine.getControls();
2583
2584    }
2585    catch (Exception ee)
2586    {
2587      System.out.println(ee);
2588    }
2589    log_.endMethod();
2590  }
2591
2592
2593  /**
2594   * Reads from the oggBitStream_ a specified number of Bytes(bufferSize_) worth
2595   * sarting at index and puts them in the specified buffer[].
2596   *
2597   * @param buffer
2598   * @param index
2599   * @param bufferSize_
2600   * @return             the number of bytes read or -1 if error.
2601   */
2602  private int readFromStream(byte[] buffer, int index, int bufferSize_)
2603  {
2604    final String methodName = className_ + ": readFromStream(byte[],int,int)";
2605    //log_.startMethod(methodName);
2606    int bytes = 0;
2607    try
2608    {
2609      bytes = oggBitStream_.read(buffer, index, bufferSize_);
2610      progressCount_ += bytes;
2611    }
2612    catch (Exception e)
2613    {
2614      System.out.println("Cannot Read Selected Song");
2615      log_.minor("Cannot Read Selected Song - index=" + index);
2616      bytes = -1;
2617    }
2618    //log_.endMethod();
2619    return bytes;
2620  }
2621
2622
2623
2624  /**
2625   * Helper method to encapsulate the starting of the timeWatcherRunnable_.*
2626   */
2627  private void startTimer()
2628  {
2629    final String methodName = className_ + ": startTimer()";
2630    log_.startMethod(methodName);
2631    if (timeWatcherThread_ == null)
2632    {
2633      timeWatcherThread_ = new TimerThread();
2634      timeWatcherThread_.start();
2635    }
2636    else if (!timeWatcherThread_.isAlive())
2637    {
2638      timerRunning_ = false;
2639      timeWatcherThread_ = new TimerThread();
2640      timeWatcherThread_.start();
2641    }
2642    else if (!timeWatcherThread_.isAlive())
2643    {
2644      timeWatcherThread_ = new TimerThread();
2645      timeWatcherThread_.start();
2646    }
2647    log_.endMethod();
2648  }
2649
2650
2651  /**
2652   * Attempts to Play the Ogg File At the Specified URL. It checks the URL , updates
2653   * the buttons and then starts the playerThread.
2654   *
2655   * @param url  the url for the song to play
2656   */
2657  private void tryPlay(URL url)
2658  {
2659    final String methodName = className_ + ": tryPlay(URL)";
2660    log_.startMethod(methodName);
2661    Util.sleep(1000);
2662    oggBitStream_ = null;
2663
2664    try
2665    {
2666      URLConnection urlc = url.openConnection();
2667      songProgress.setMaximum((urlc.getContentLength() > 0 ?
2668        urlc.getContentLength() : 0));
2669      log_.debug("Getting the Ogg Bitstream for URL="+Util.decodeURL(url.toString()));
2670      oggBitStream_ = urlc.getInputStream();
2671    }
2672    catch (Exception ee)
2673    {
2674      log_.minor("Can't get a connection to the song file",ee);
2675      System.err.println(ee);
2676    }
2677    if (oggBitStream_ == null)
2678    {
2679      log_.minor("Can't get a connection to the song file");
2680      System.out.println("Nope, No Go on the Stream");
2681    }
2682    else
2683    {
2684      log_.debug("Ogg Bitstream created: " + Util.decodeURL(url.toString()));
2685      if (!this.running_as_applet)
2686        appFrame_.setTitle(APP_NAME + " - " + Util.decodeURL(url.toString()));
2687      playerThread_ = new Thread(this);
2688      button.setIcon(iconStop_);
2689      miniButtonPlay.setIcon(iconMiniStop_);
2690      if (miniViewShowing_)
2691      {
2692        buttonPause.setEnabled(true);
2693      }
2694      else
2695      {
2696        miniButtonPause.setEnabled(true);
2697      }
2698      playing_ = true;
2699      playerThread_.start();
2700    }
2701    Util.sleep(1000);
2702    log_.endMethod();
2703  }
2704
2705
2706  /**
2707   * Attempts to Play the Ogg File At the Specified URL String. It checks the URL,
2708   * updates the buttons and then starts the playerThread.
2709   *
2710   * @param item  Description of Parameter
2711   */
2712  private void tryPlay(String item)
2713  {
2714    final String methodName = className_ + ": tryPlay(String)";
2715    log_.startMethod(methodName);
2716    Util.sleep(1000);
2717    oggBitStream_ = null;
2718
2719    try
2720    {
2721      URL url = null;
2722      if (running_as_applet)
2723      {
2724        url = new URL(getCodeBase(), item);
2725      }
2726      else
2727      {
2728        url = new URL(item);
2729      }
2730      URLConnection urlc = url.openConnection();
2731      songProgress.setMaximum((urlc.getContentLength() > 0 ?
2732        urlc.getContentLength() : 0));
2733      oggBitStream_ = urlc.getInputStream();
2734    }
2735    catch (Exception ee)
2736    {
2737      if (running_as_applet)
2738      {
2739        System.err.println(ee);
2740      }
2741    }
2742    if (oggBitStream_ == null && !running_as_applet)
2743    {
2744      System.out.println("Trying to open file " + item);
2745      try
2746      {
2747        oggBitStream_ = new FileInputStream(item);
2748        songProgress.setMaximum((int) (new File(item)).length());
2749        System.out.println("Progress Max=" + songProgress.getMaximum());
2750      }
2751      catch (Exception ee)
2752      {
2753        System.err.println(ee);
2754      }
2755    }
2756    if (oggBitStream_ == null)
2757    {
2758      System.out.println("Nope, No Go on the Stream");
2759      System.out.println("Clean up Song.");
2760      timerRunning_ = false;
2761      try
2762      {
2763        if (oggBitStream_ != null)
2764        {
2765          oggBitStream_.close();
2766        }
2767        //playerThread_ = null;
2768        playing_ = false;
2769      }
2770      catch (Exception e)
2771      {
2772      }
2773      button.setIcon(iconPlay_);
2774      miniButtonPlay.setIcon(iconMiniPlay_);
2775      if (miniViewShowing_)
2776      {
2777        buttonPause.setEnabled(false);
2778      }
2779      else
2780      {
2781        miniButtonPause.setEnabled(false);
2782      }
2783    }
2784    else
2785    {
2786      System.out.println("Select: " + item);
2787      appFrame_.setTitle(APP_NAME + " - " + item);
2788      playerThread_ = new Thread(this);
2789      button.setIcon(iconStop_);
2790      miniButtonPlay.setIcon(iconMiniStop_);
2791      if (miniViewShowing_)
2792      {
2793        buttonPause.setEnabled(true);
2794      }
2795      else
2796      {
2797        miniButtonPause.setEnabled(true);
2798      }
2799      playing_ = true;
2800      playerThread_.start();
2801    }
2802    Util.sleep(1000);
2803    log_.endMethod();
2804  }
2805
2806
2807  /**
2808   * Gets the Vorbis comment popup text for the selected song info.
2809   *
2810   * @param songIndex is the playlist index to popup
2811   * @return the string for the pop-up holding the songs Vorbis comments
2812   */
2813  private String getSongCommentPopup(int songIndex)
2814  {
2815    final String methodName = className_ + ": getSongCommentPopup()";
2816    log_.startMethod(methodName);
2817    String newString = "<html><body><font face=\"Arial, Helvetica\" size=\"-2\">";
2818    newString += playList.getSongInfo( songIndex );
2819    newString += "</font>";
2820//    newString += "<br>";
2821//    newString += playList.getSongInfo(playListComboBox.getSelectedIndex());
2822    newString += "</body></html>";
2823    log_.endMethod();
2824    return newString;
2825  }
2826
2827
2828  /**
2829   * Updates the tooltip popup text for the Display area with the latest song info.
2830   *
2831   * @return the string for the pop-up holding the songs Vorbis comments
2832   */
2833  private String updateDisplayPopup()
2834  {
2835    final String methodName = className_ + ": updateDisplayPopup()";
2836    log_.startMethod(methodName);
2837    String newString = "<html><body><font face=\"Arial, Helvetica\" size=\"-2\">";
2838    for (int i = 0; i < songComments_.size(); i++)
2839    {
2840      newString += songComments_.get(i);
2841      if (i+1 < songComments_.size())
2842        newString += "<br>";
2843    }
2844    newString += "</font>";
2845//    newString += "<br>";
2846//    newString += playList.getSongInfo(playListComboBox.getSelectedIndex());
2847    newString += "</body></html>";
2848    displayPanel.setToolTipText(newString);
2849    miniTimeLabelValue.setToolTipText(newString);
2850    miniDragButton.setToolTipText(newString);
2851    log_.endMethod();
2852    return newString;
2853  }
2854
2855
2856  /**
2857   * Gets the Menus setup.
2858   */
2859  private void initMenus()
2860  {
2861    final String methodName = className_ + ": initMenus()";
2862    log_.startMethod(methodName);
2863
2864    JMenuItem miniView = new JMenuItem("View Size Toggle");
2865    miniView.addActionListener(
2866      new ActionListener()
2867      {
2868        public void actionPerformed(ActionEvent e)
2869        {
2870          if (e.getActionCommand().equals("View Size Toggle"))
2871          {
2872            if (miniViewShowing_)
2873            {
2874              showMiniView(false);
2875            }
2876            else
2877            {
2878              showMiniView(true);
2879            }
2880          }
2881        }
2882      }
2883      );
2884
2885    JMenu playlistMenu = new JMenu("Playlist Admin");
2886    JMenu favouritesMenu = new JMenu("Favourites");
2887    JMenuItem deselectAllFavs = new JMenuItem("De-Select All Favourite Checks");
2888    JMenuItem selectAllFavs = new JMenuItem("Select All Songs as Favourites");
2889    JMenuItem sortByFilename = new JMenuItem("Sort By Filename");
2890    JMenuItem sortByAlbum = new JMenuItem("Sort By Artist Albums");
2891    JMenuItem addUrl = new JMenuItem("Add From URL...");
2892    JMenuItem addFile = new JMenuItem("Add From File...");
2893    JMenuItem addPlaylistFile = new JMenuItem("Add From Playlist File...");
2894    JMenuItem savePlaylist = new JMenuItem("Save Playlist File...");
2895    JMenuItem saveFavourites = new JMenuItem("Save Favourites Playlist File...");
2896    JMenuItem deleteSelected = new JMenuItem("Delete Selected Song");
2897    JMenuItem clearAll = new JMenuItem("Delete ALL");
2898    favouritesMenu.add(selectAllFavs);
2899    favouritesMenu.add(deselectAllFavs);
2900    playlistMenu.add(favouritesMenu);
2901    playlistMenu.addSeparator();
2902    playlistMenu.add(sortByFilename);
2903    playlistMenu.add(sortByAlbum);
2904    playlistMenu.addSeparator();
2905    playlistMenu.add(addUrl);
2906    playlistMenu.add(addFile);
2907    playlistMenu.add(addPlaylistFile);
2908    playlistMenu.addSeparator();
2909    playlistMenu.add(savePlaylist);
2910    playlistMenu.add(saveFavourites);
2911    playlistMenu.addSeparator();
2912    playlistMenu.add(deleteSelected);
2913    playlistMenu.add(clearAll);
2914    selectAllFavs.addActionListener(selectAllAsFavouriteSongActionListener);
2915    deselectAllFavs.addActionListener(deselectAllAsFavouriteSongActionListener);
2916    deleteSelected.addActionListener(deleteSelectedSongActionListener);
2917    clearAll.addActionListener(deleteAllActionListener);
2918    sortByFilename.addActionListener(sortByFilenameActionListener);
2919    sortByAlbum.addActionListener(sortByAlbumActionListener);
2920    addFile.addActionListener(addSongActionListener);
2921    addUrl.addActionListener(addURLActionListener);
2922    addPlaylistFile.addActionListener(addFromPlaylistActionListener);
2923    savePlaylist.addActionListener(savePlaylistActionListener);
2924    saveFavourites.addActionListener(saveFavouritesActionListener);
2925
2926    JMenu proxyMenu = new JMenu("Proxy Settings");
2927    JMenuItem proxyUseMenu = new JMenuItem("Use A Proxy ...");
2928    JMenuItem proxyHostMenu = new JMenuItem("Proxy Host ...");
2929    JMenuItem proxyPortMenu = new JMenuItem("Proxy Port ...");
2930    JMenuItem proxyAuthenticationMenu = new JMenuItem("Proxy Authentication ...");
2931    JMenuItem proxyUserMenu = new JMenuItem("Proxy Username ...");
2932    JMenuItem proxyPassMenu = new JMenuItem("Proxy user Password ...");
2933    JMenuItem noProxyMenu = new JMenuItem("No Proxy List ...");
2934    proxyMenu.add(proxyUseMenu);
2935    //proxyMenu.add(proxyHostMenu);
2936    //proxyMenu.add(proxyPortMenu);
2937    //proxyMenu.add(noProxyMenu);
2938    //proxyMenu.addSeparator();
2939    proxyMenu.add(proxyAuthenticationMenu);
2940    //proxyMenu.add(proxyUserMenu);
2941    //proxyMenu.add(proxyPassMenu);
2942
2943    proxyUseMenu.addActionListener(
2944      new ActionListener()
2945      {
2946        public void actionPerformed(ActionEvent e)
2947        {
2948          String result = JOptionPane.showInputDialog("Use a proxy (true/false)?",
2949                             ( areWeUsingProxy_?"true":"false"));
2950          if(result != null)
2951          {
2952            areWeUsingProxy_ = Boolean.parseBoolean(result);
2953            log_.debug("Proxy Use ="+areWeUsingProxy_);
2954          }
2955
2956          if (areWeUsingProxy_)
2957          {
2958            result = JOptionPane.showInputDialog("Proxy Hostname/IP?",proxyHost_);
2959            if(result != null)
2960            {
2961              proxyHost_ = result;
2962              log_.debug("Proxy Host is now="+proxyHost_);
2963            }
2964
2965            result = JOptionPane.showInputDialog("Proxy Port?",proxyPort_);
2966            if(result != null)
2967            {
2968              proxyPort_ = result;
2969              log_.debug("Proxy Port is now="+proxyPort_);
2970            }
2971
2972            result = JOptionPane.showInputDialog("No Proxy list?",proxyNoProxy_);
2973            if(result != null)
2974            {
2975              proxyNoProxy_ = result;
2976              log_.debug("No Proxy for: "+proxyNoProxy_);
2977            }
2978          }
2979          else
2980          {
2981            //proxyHost_="";proxyPort_="";proxyNoProxy_="";
2982          }
2983
2984          initProxy();
2985          if (lastFM_userId!=null && !lastFM_userId.equals(""))
2986            sc_ = handshakeWithLastfm(lastFM_userId);
2987
2988        }
2989      }
2990      );
2991
2992    proxyAuthenticationMenu.addActionListener(
2993      new ActionListener()
2994      {
2995        public void actionPerformed(ActionEvent e)
2996        {
2997          String result = JOptionPane.showInputDialog("Does the proxy require user authentication (true/false)?",
2998            ( useProxyAuthentication_?"true":"false"));
2999          if(result != null)
3000          {
3001            useProxyAuthentication_ = Boolean.parseBoolean(result);
3002            log_.debug("Proxy User is now="+proxyUsername_);
3003          }
3004
3005          if (useProxyAuthentication_)
3006          {
3007            result = JOptionPane.showInputDialog("Proxy Username?",proxyUsername_);
3008            if(result != null)
3009            {
3010              proxyUsername_ = result;
3011              log_.debug("Proxy User is now="+proxyUsername_);
3012            }
3013
3014            result = JOptionPane.showInputDialog("Proxy Password?",proxyPassword_);
3015            if(result != null)
3016            {
3017              proxyPassword_ = result;
3018              log_.debug("Proxy Password is now="+proxyPassword_);
3019            }
3020          }
3021          initProxy();
3022          if (lastFM_userId!=null && !lastFM_userId.equals(""))
3023            sc_ = handshakeWithLastfm(lastFM_userId);
3024        }
3025      }
3026      );
3027
3028    JMenuItem lastfmUserMenu = new JMenuItem("Last.fm UserID ...");
3029    lastfmUserMenu.addActionListener(
3030      new ActionListener()
3031      {
3032        public void actionPerformed(ActionEvent e)
3033        {
3034          String result = JOptionPane.showInputDialog("Last.fm Username?",lastFM_userId);
3035
3036          if(result != null)
3037          {
3038            lastFM_userId = result;
3039            log_.debug("Last.fm userID is now="+lastFM_userId);
3040          }
3041          result = JOptionPane.showInputDialog("Last.fm Password?",lastFM_userPass);
3042
3043          if(result != null)
3044          {
3045            lastFM_userPass = result;
3046            log_.debug("Last.fm userPassword is now="+lastFM_userPass);
3047          }
3048        }
3049      }
3050      );
3051
3052    JMenuItem bufferSizeMenu = new JMenuItem("Set Vorbis Buffer Size...");
3053    bufferSizeMenu.addActionListener(
3054      new ActionListener()
3055      {
3056        public void actionPerformed(ActionEvent e)
3057        {
3058          Object options[] = new Object[6];
3059          options[0] = "256";
3060          options[1] = "512";
3061          options[2] = "1024";
3062          options[3] = "2048";
3063          options[4] = "4096";
3064          options[5] = "8192";
3065
3066          Object result = JOptionPane.showInputDialog(getParent(),
3067            null, "Vorbis buffer size (Bytes)",
3068            JOptionPane.QUESTION_MESSAGE,
3069            null, options, options[2]);
3070
3071          if(result != null)
3072          {
3073            bufferMultiple_ = (Integer.parseInt((String)result))/256;
3074            bufferSize_ = bufferMultiple_ * 256 * 2;
3075            log_.debug("BufferMultiple is now="+bufferMultiple_);
3076          }
3077        }
3078      }
3079      );
3080
3081    JMenuItem debugLevelMenu = new JMenuItem("Set Debug Logging Level...");
3082    debugLevelMenu.addActionListener(
3083      new ActionListener()
3084      {
3085        public void actionPerformed(ActionEvent e)
3086        {
3087          Object options[] = new Object[6];
3088          options[0] = "NONE";
3089          options[1] = "QUIET";
3090          options[2] = "MINOR";
3091          options[3] = "MAJOR";
3092          options[4] = "DEBUG";
3093          options[5] = "FULL";
3094
3095          Object result = JOptionPane.showInputDialog(getParent(),
3096            null, "Debug Logging Level",
3097            JOptionPane.QUESTION_MESSAGE,
3098            null, options, options[0]);
3099
3100          if(result != null)
3101          {
3102            short level = -1;
3103            if ("NONE".equals(result)) level = Log.NONE;
3104            else if ("DEBUG".equals(result)) level = Log.DEBUG;
3105            else if ("MINOR".equals(result)) level = Log.MINOR;
3106            else if ("MAJOR".equals(result)) level = Log.MAJOR;
3107            else if ("FULL".equals(result)) level = Log.FULL;
3108            else if ("QUIET".equals(result)) level = Log.QUIET;
3109            if (level != -1)
3110            {
3111              log_.debug("Setting Log Level to "+level);
3112              log_.setLogLevel(level);
3113            }
3114            log_.debug("Logging Level is now="+log_.getLogLevel());
3115          }
3116        }
3117      }
3118      );
3119
3120    JMenuItem autoPlayMenu = new JMenuItem("Auto Start Song Play On Startup...");
3121    autoPlayMenu.addActionListener(
3122      new ActionListener()
3123      {
3124        public void actionPerformed(ActionEvent e)
3125        {
3126          Object options[] = new Object[2];
3127          options[0] = "Yes";
3128          options[1] = "No";
3129
3130          Object result = JOptionPane.showInputDialog(getParent(),
3131            null, "Auto Play on startup?",
3132            JOptionPane.QUESTION_MESSAGE,
3133            null, options, options[0]);
3134
3135          if(result != null)
3136          {
3137            if ("Yes".equals(result)) autoPlayOnStart_ = true;
3138            else if ("No".equals(result)) autoPlayOnStart_ = false;
3139          }
3140        }
3141      }
3142      );
3143
3144    JMenu fontChoiceMenu = new JMenu("Set Display Font");
3145    String[] availableFontNames =
3146      USER_GRAPHIC_ENV.getAvailableFontFamilyNames();
3147    for (int i = 0; i < availableFontNames.length; i++)
3148    {
3149      JMenu fontChoice = new JMenu(availableFontNames[i]);
3150      JMenuItem size8 = new JMenuItem("8");
3151      JMenuItem size9 = new JMenuItem("9");
3152      JMenuItem size10 = new JMenuItem("10");
3153      JMenuItem size11 = new JMenuItem("11");
3154      JMenuItem size12 = new JMenuItem("12");
3155      JMenuItem size13 = new JMenuItem("13");
3156      JMenuItem size14 = new JMenuItem("14");
3157      if (!availableFontNames[i].startsWith("V") &&
3158        !availableFontNames[i].startsWith(".") &&
3159        !availableFontNames[i].endsWith("1.1"))
3160      {
3161        size8.addActionListener(
3162          new ActionListener()
3163          {
3164            public void actionPerformed(ActionEvent e)
3165            {
3166              JMenu myParent = (JMenu)
3167                ((JPopupMenu)
3168                ((JMenuItem) e.getSource()).getParent()).getInvoker();
3169              int mySize = Integer.parseInt(e.getActionCommand());
3170              setDisplayFont(new Font(myParent.getText(),
3171                Font.PLAIN,
3172                mySize));
3173            }
3174          }
3175          );
3176        size9.addActionListener(
3177          new ActionListener()
3178          {
3179            public void actionPerformed(ActionEvent e)
3180            {
3181              JMenu myParent = (JMenu)
3182                ((JPopupMenu)
3183                ((JMenuItem) e.getSource()).getParent()).getInvoker();
3184              int mySize = Integer.parseInt(e.getActionCommand());
3185              setDisplayFont(new Font(myParent.getText(),
3186                Font.PLAIN,
3187                mySize));
3188            }
3189          }
3190          );
3191        size10.addActionListener(
3192          new ActionListener()
3193          {
3194            public void actionPerformed(ActionEvent e)
3195            {
3196              JMenu myParent = (JMenu)
3197                ((JPopupMenu)
3198                ((JMenuItem) e.getSource()).getParent()).getInvoker();
3199              int mySize = Integer.parseInt(e.getActionCommand());
3200              setDisplayFont(new Font(myParent.getText(),
3201                Font.PLAIN,
3202                mySize));
3203              System.out.println("Setting FONT = " + myParent.getText() + "  " +
3204                mySize);
3205            }
3206          }
3207          );
3208        size11.addActionListener(
3209          new ActionListener()
3210          {
3211            public void actionPerformed(ActionEvent e)
3212            {
3213              JMenu myParent = (JMenu)
3214                ((JPopupMenu)
3215                ((JMenuItem) e.getSource()).getParent()).getInvoker();
3216              int mySize = Integer.parseInt(e.getActionCommand());
3217              setDisplayFont(new Font(myParent.getText(),
3218                Font.PLAIN,
3219                mySize));
3220            }
3221          }
3222          );
3223        size12.addActionListener(
3224          new ActionListener()
3225          {
3226            public void actionPerformed(ActionEvent e)
3227            {
3228              JMenu myParent = (JMenu)
3229                ((JPopupMenu)
3230                ((JMenuItem) e.getSource()).getParent()).getInvoker();
3231              int mySize = Integer.parseInt(e.getActionCommand());
3232              setDisplayFont(new Font(myParent.getText(),
3233                Font.PLAIN,
3234                mySize));
3235            }
3236          }
3237          );
3238        size13.addActionListener(
3239          new ActionListener()
3240          {
3241            public void actionPerformed(ActionEvent e)
3242            {
3243              JMenu myParent = (JMenu)
3244                ((JPopupMenu)
3245                ((JMenuItem) e.getSource()).getParent()).getInvoker();
3246              int mySize = Integer.parseInt(e.getActionCommand());
3247              setDisplayFont(new Font(myParent.getText(),
3248                Font.PLAIN,
3249                mySize));
3250            }
3251          }
3252          );
3253        size14.addActionListener(
3254          new ActionListener()
3255          {
3256            public void actionPerformed(ActionEvent e)
3257            {
3258              JMenu myParent = (JMenu)
3259                ((JPopupMenu)
3260                ((JMenuItem) e.getSource()).getParent()).getInvoker();
3261              int mySize = Integer.parseInt(e.getActionCommand());
3262              setDisplayFont(new Font(myParent.getText(),
3263                Font.PLAIN,
3264                mySize));
3265            }
3266          }
3267          );
3268        fontChoice.add(size8);
3269        fontChoice.add(size9);
3270        fontChoice.add(size10);
3271        fontChoice.add(size11);
3272        fontChoice.add(size12);
3273        fontChoice.add(size13);
3274        fontChoice.add(size14);
3275        fontChoiceMenu.add(fontChoice);
3276      }
3277    }
3278
3279    JMenuItem backColourChange = new JMenuItem("Set Background Colour...");
3280    backColourChange.addActionListener(
3281      new ActionListener()
3282      {
3283        public void actionPerformed(ActionEvent e)
3284        {
3285          if (e.getActionCommand().equals("Set Background Colour..."))
3286          {
3287            Color newColour = JColorChooser.showDialog(appFrame_,
3288              "New Background Colour",
3289              mainBackColour_);
3290            mainBackColour_ = newColour;
3291            showTextures_ = false;
3292            setColours();
3293            appFrame_.validate();
3294          }
3295        }
3296      }
3297      );
3298
3299    JMenu textureChoiceMenu = new JMenu("Set Background Texture");
3300    if (availableTextureNames_==null)
3301      availableTextureNames_ = DEFAULT_TEXTURE_NAMES;
3302    for (int i = 0; i < availableTextureNames_.length; i++)
3303    {
3304      JMenuItem textureChoice = new JMenuItem(availableTextureNames_[i]);
3305      textureChoice.addActionListener(
3306        new ActionListener()
3307        {
3308          public void actionPerformed(ActionEvent e)
3309          {
3310            backgroundTextureFilename_ = "/images/textures/" +
3311              e.getActionCommand();
3312            System.out.println("Setting Background to : "+
3313              backgroundTextureFilename_);
3314            showTextures_ = true;
3315            setColours();
3316            //           controlPanel.invalidate();
3317            appFrame_.paintComponents(appFrame_.getGraphics());
3318          }
3319        }
3320        );
3321      textureChoiceMenu.add(textureChoice);
3322    }
3323
3324    JMenuItem aboutBox = new JMenuItem("About jOggPlayer...");
3325    aboutBox.addActionListener(
3326      new ActionListener()
3327      {
3328        public void actionPerformed(ActionEvent e)
3329        {
3330          if (e.getActionCommand().equals("About jOggPlayer..."))
3331          {
3332            JAboutBox a = new JAboutBox(aboutGraphic_,
3333              "About jOggPlayer",
3334              "<B>jOggPlayer</B><BR>GUI Enhanced Pure Java Ogg Vorbis player.",
3335              VERSION, helpHtmlStr_);
3336          }
3337        }
3338      }
3339      );
3340
3341    JMenuItem helpWindow = new JMenuItem("Help...");
3342    helpWindow.addActionListener(
3343      new ActionListener()
3344      {
3345        public void actionPerformed(ActionEvent e)
3346        {
3347          if (e.getActionCommand().equals("Help..."))
3348          {
3349            Object [] options = {"Done"};
3350            JEditorPane htmlPane = new JEditorPane("text/html",
3351                           "<html><body><A name=\"Top\"></A>" +
3352                            jOggPlayer.helpHtmlStr_+
3353                            "</body></html>");
3354            htmlPane.setEditable(false);
3355
3356            //CalHTMLPane calPane = new CalHTMLPane();
3357
3358            JScrollPane htmlScrollPane = new JScrollPane();
3359            htmlScrollPane.getViewport().add(htmlPane);
3360            htmlScrollPane.setVerticalScrollBarPolicy(
3361                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
3362            htmlScrollPane.setPreferredSize(new Dimension(640, 480));
3363            // ensure the top of the help info is visible
3364            htmlPane.scrollRectToVisible(new Rectangle(0,0));
3365            htmlScrollPane.getViewport().scrollRectToVisible(new Rectangle(0,0));
3366
3367            JOptionPane pane = new JOptionPane(
3368                            (Object) htmlScrollPane,
3369                            JOptionPane.INFORMATION_MESSAGE,
3370                            JOptionPane.DEFAULT_OPTION,
3371                            new ImageIcon(),
3372                            options) ;
3373            JDialog dialog = pane.createDialog(getParent(), "jOggPlayer Help");
3374            dialog.show();
3375            // ensure the top of the help info is visible
3376            //htmlPane.scrollRectToVisible(
3377            //  new Rectangle(0,0));
3378            /*calPane.showHTMLDocument(
3379                           "<html><body><A name=\"Top\"></A>" +
3380                            jOggPlayer.helpHtmlStr_+
3381                            "</body></html>");
3382            calPane.scrollToReference("Top",null);
3383            calPane.requestFocus();*/
3384          }
3385        }
3386      }
3387      );
3388
3389    JMenu optionsMenu = new JMenu("Options");
3390
3391    mainMenu.add(playlistMenu);
3392    mainMenu.addSeparator();
3393    if(!this.running_as_applet)
3394    {
3395      mainMenu.add(miniView);
3396    }
3397    optionsMenu.add(bufferSizeMenu);
3398    optionsMenu.add(debugLevelMenu);
3399    optionsMenu.add(autoPlayMenu);
3400    optionsMenu.addSeparator();
3401    optionsMenu.add(proxyMenu);
3402    optionsMenu.add(lastfmUserMenu);
3403    optionsMenu.addSeparator();
3404    optionsMenu.add(fontChoiceMenu);
3405    optionsMenu.add(textureChoiceMenu);
3406    optionsMenu.add(backColourChange);
3407    mainMenu.add(optionsMenu);
3408    mainMenu.addSeparator();
3409    mainMenu.add(helpWindow);
3410    mainMenu.add(aboutBox);
3411    log_.endMethod();
3412  }
3413
3414
3415  /**
3416   * Switches the Playlist panel on/off.
3417   *
3418   * @param showIt  specifies whether to view or not.
3419   */
3420  private void showPlaylistPanel(boolean showIt)
3421  {
3422    final String methodName = className_ + ": showPlaylistPanel(" + showIt + ")";
3423    log_.startMethod(methodName);
3424    if (showIt)
3425    {
3426      log_.debug("PlayListcomboBox has " + playListComboBox.getItemCount() +
3427        " songs.");
3428      String tempTitle = playListComboBox.getSelectedItemName();
3429      if (tempTitle == null || tempTitle.equals("") )
3430      {
3431        tempTitle = "Empty Playlist";
3432      }
3433      //else
3434        //System.out.println("PlayListcomboBox has " + tempTitle +
3435          //" selected.");
3436      playListComboBox.setText(tempTitle);
3437      frameCurrentSize_ = appFrame_.getSize();
3438      Dimension innerFooterSize = innerFooterPanel.getPreferredSize();
3439      playListShowing_ = true;
3440      appFrame_.setResizable(true);
3441      panel.add(innerFooterPanel, BorderLayout.SOUTH);
3442      appFrame_.setSize((int) (frameCurrentSize_.getWidth()),
3443        (int) (frameCurrentSize_.getHeight()
3444         + innerFooterSize.getHeight()));
3445      innerFooterPanel.invalidate();
3446      appFrame_.validate();
3447      //appFrame_.setResizable(false);
3448    }
3449    else
3450    {
3451      Dimension innerFooterSize = innerFooterPanel.getPreferredSize();
3452      frameCurrentSize_ = appFrame_.getSize();
3453      playListShowing_ = false;
3454      appFrame_.setResizable(true);
3455      panel.remove(innerFooterPanel);
3456      appFrame_.setSize((int) (frameCurrentSize_.getWidth()),
3457        (int) (frameCurrentSize_.getHeight()
3458         - innerFooterSize.getHeight()));
3459      appFrame_.validate();
3460      //appFrame_.setResizable(false);
3461    }
3462    log_.endMethod();
3463  }
3464
3465
3466  /**
3467   * Switches to or from the mini view.
3468   *
3469   * @param showIt  specifies whether to go to mini view or not.
3470   */
3471  private static void showMiniView(boolean showIt)
3472  {
3473    final String methodName = className_ + ": showMiniView(" + showIt + ")";
3474    log_.startMethod(methodName);
3475    /*
3476     *  Show or Hide the playlist
3477     */
3478    if (showIt)
3479    {
3480      appFrame_.setVisible(false);
3481      popUpWin_.pack();
3482      popUpWin_.setLocation(xpos, ypos);
3483      popUpWin_.setVisible(true);
3484      popUpWin_.toFront();
3485      miniViewShowing_ = true;
3486    }
3487    else
3488    {
3489      popUpWin_.setVisible(false);
3490      appFrame_.setVisible(true);
3491      appFrame_.toFront();
3492      miniViewShowing_ = false;
3493    }
3494    log_.endMethod();
3495  }
3496
3497
3498  /**
3499   * Gets the GUI setup *
3500   */
3501  private void initUI()
3502  {
3503    final String methodName = className_ + ": initUI()";
3504    log_.startMethod(methodName);
3505    initMenus();
3506    FileDrop.Listener fDropListener =
3507      new FileDrop.Listener()
3508      {
3509        public void filesDropped(File[] files)
3510        {
3511          // handle file drop
3512          System.out.println("Dropped " + files.length + " Files");
3513          String tempEntry = null;
3514          for (int i = 0; i < files.length; i++)
3515          {
3516            tempEntry = files[i].getAbsolutePath();
3517            if (!playList.contains(tempEntry))
3518            {
3519              String s = playList.addSong(Util.getFileBaseURL(tempEntry));
3520              JCheckBox chBox = new JCheckBox(s, true);
3521
3522              playListComboBox.addItem(chBox);
3523            }
3524          }
3525          playList.sortSongs();
3526          playListComboBox.removeAllItems();
3527          String[] playListNames = playList.getSongFileNames();
3528          JCheckBox jc = null;
3529          for (int i = 0; i < playListNames.length; i++)
3530          {
3531            jc = new JCheckBox(playListNames[i], true);
3532            jc.setToolTipText(getSongCommentPopup(i));
3533            playListComboBox.addItem(jc);
3534          }
3535          playListComboBox.validate();
3536        } // end filesDropped
3537      };
3538
3539    panel.setLayout(new BorderLayout(0, 0));
3540    //popUpWin_.getContentPane().setLayout(
3541    //  new BoxLayout(popUpWin_,BoxLayout.X_AXIS));
3542    headerPanel.setLayout(new BoxLayout(headerPanel, BoxLayout.X_AXIS));
3543    bodyPanel.setLayout(new BorderLayout(0, 0));
3544    dragableMiniViewPanel.setLayout(new BorderLayout(0, 0));
3545    miniViewPanel.setLayout(new BoxLayout(miniViewPanel, BoxLayout.X_AXIS));
3546    /* we don't want the mini Label wrapping, so BoxLayout*/
3547    miniDragLabel.setLayout(new BoxLayout(miniDragLabel, BoxLayout.X_AXIS));
3548    leftPanel.setLayout(new BorderLayout(0, 0));
3549    innerPanel.setLayout(new BoxLayout(innerPanel, BoxLayout.Y_AXIS));
3550    miniViewWindowControlPanel.setLayout(new BorderLayout(0, 0));
3551    //new BoxLayout(miniViewWindowControlPanel, BoxLayout.X_AXIS));
3552    //rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
3553    innerHeaderPanel.setLayout(new BoxLayout(innerHeaderPanel,
3554      BoxLayout.X_AXIS));
3555    displayPanel.setLayout(new BorderLayout(0, 0));
3556    innerDisplayPanel.setLayout(new BorderLayout(0, 0));
3557    controlPanel.setLayout(new BorderLayout(0, 0));
3558    innerFooterPanel.setLayout(new BorderLayout());
3559
3560    //checkPanel.setLayout(new FlowLayout(FlowLayout.CENTER,0,0));//BoxLayout(checkPanel, BoxLayout.X_AXIS));
3561    checkPanel.setLayout(new BoxLayout(checkPanel, BoxLayout.X_AXIS));
3562    innerLeftDisplayPanel.setLayout(new GridLayout(0, 1));
3563    innerRightDisplayPanel.setLayout(new GridLayout(0, 1));
3564    /*
3565     *  innerPlaylistPanel.setLayout(new BoxLayout(innerPlaylistPanel,
3566     *  BoxLayout.X_AXIS));
3567     */
3568    displayPanel.setPreferredSize(new Dimension(displayWidth_, displayHeight_));
3569    innerDisplayPanel.setPreferredSize(
3570      new Dimension(innerDisplayPanelWidth_,
3571      innerDisplayPanelHeight_));
3572    innerLeftDisplayPanel.setPreferredSize(
3573      new Dimension(innerLeftDisplayPanelWidth_,
3574      displayHeight_ - songProgressHeight_));
3575    //innerRightDisplayPanel.setPreferredSize(
3576    //new Dimension(displayWidth_ - innerLeftDisplayPanelWidth_,
3577    //displayHeight_));
3578    //displayPanel.setBorder(BorderFactory.createBevelBorder((BevelBorder.LOWERED)));
3579    artistLabel.setFont(displayFontBold_);
3580    titleLabel.setFont(displayFontBold_);
3581    timeLabel.setFont(displayFontBold_);
3582    artistLabelValue.setFont(displayFont_);
3583    titleLabelValue.setFont(displayFont_);
3584    timeLabelValue.setFont(displayFont_);
3585    miniTimeLabelValue.setFont(displayFont_);
3586
3587    artistLabel.setVerticalAlignment(ColouredLabel.TOP);
3588    titleLabel.setVerticalAlignment(ColouredLabel.TOP);
3589    timeLabel.setVerticalAlignment(ColouredLabel.TOP);
3590    artistLabelValue.setVerticalAlignment(ColouredLabel.TOP);
3591    titleLabelValue.setVerticalAlignment(ColouredLabel.TOP);
3592    timeLabelValue.setVerticalAlignment(ColouredLabel.TOP);
3593    miniTimeLabelValue.setVerticalAlignment(ColouredLabel.TOP);
3594    miniDragLabel.setVerticalAlignment(ColouredLabel.BOTTOM);
3595
3596    popUpWin_.getContentPane().setBackground(displayBackColour_);
3597
3598    playList.sortSongs();
3599    playListComboBox = new JCheckDropDown(playList.getSongFileNames());
3600    playListComboBox.setFont(new Font(playListComboBox.getFont().getFontName(),playListComboBox.getFont().getStyle(),uiFontSize_));
3601
3602    String currTitle = null;
3603    if (playListComboBox.getNumItems() > 0)
3604    {
3605      playListComboBox.setSelectedIndex(0);
3606    }
3607    else
3608    {
3609      playListComboBox.setText("Empty Playlist");
3610    }
3611
3612    songProgress.setPreferredSize(
3613      new Dimension(displayWidth_ - 20,
3614      songProgressHeight_));
3615    //songProgress.setBorder(BorderFactory.createBevelBorder(BevelBorder.RAISED));
3616    volumeSlider_.setToolTipText("Volume: " + maxVolScale_);
3617
3618    volumeSlider_.setBorder(BorderFactory.createBevelBorder(
3619      BevelBorder.LOWERED));
3620    volumeSlider_.setFont(new Font(volumeSlider_.getFont().getFontName(),volumeSlider_.getFont().getStyle(),uiFontSize_));
3621    volumeSlider_.setPaintLabels(true);
3622    volumeSlider_.setPaintTicks(true);
3623    volumeSlider_.setMajorTickSpacing(maxVolScale_ / 2);
3624    volumeSlider_.setMinorTickSpacing(maxVolScale_ / 10);
3625    volumeSlider_.setSnapToTicks(true);
3626    volumeSlider_.setPreferredSize(
3627      new Dimension(volumeWidth_, displayHeight_ + controlHeight_-20));
3628    controlPanel.setPreferredSize(
3629      new Dimension(displayWidth_, controlHeight_));
3630    //innerPlaylistPanel.setPreferredSize(
3631    //           new Dimension(displayWidth_ + volumeWidth_, playlistHeight_));
3632    //button = new KButton("");
3633    button.setIcon(iconPlay_);
3634    button.setOpaque(false);
3635    button.setBackground(buttonBackColour_);
3636    button.setPreferredSize(
3637      new Dimension(iconPlay_.getIconWidth() + 5, iconPlay_.getIconHeight() + 5));
3638    button.setToolTipText("Play Current Song In Playlist");
3639    button.addActionListener(this);
3640    button.setBorder(BorderFactory.createBevelBorder(
3641      BevelBorder.RAISED));
3642
3643    miniButtonPlay.setIcon(iconMiniPlay_);
3644    miniButtonPlay.setOpaque(false);
3645    miniButtonPlay.setBackground(buttonBackColour_);
3646    miniButtonPlay.setPreferredSize(
3647      new Dimension(iconMiniPlay_.getIconWidth(), iconMiniPlay_.getIconHeight()));
3648    miniButtonPlay.setToolTipText("Play Current Song In Playlist");
3649    miniButtonPlay.addActionListener(this);
3650    miniButtonPlay.setBorder(BorderFactory.createBevelBorder(
3651      BevelBorder.RAISED));
3652
3653    muteButton_.setToolTipText("Mute The Volume.");
3654    muteButton_.setIcon(iconVolOn_);
3655    //muteButton_.setBorder(new javax.swing.border.EmptyBorder(0,0,0,0));
3656    muteButton_.setBorder(BorderFactory.createBevelBorder(
3657      BevelBorder.LOWERED));
3658
3659    buttonLast.addActionListener(this);
3660    buttonLast.setIcon(iconBack_);
3661    buttonLast.setOpaque(false);
3662    buttonLast.setBackground(buttonBackColour_);
3663    buttonLast.setPreferredSize(
3664      new Dimension(iconBack_.getIconWidth() + 5, iconBack_.getIconHeight() + 5));
3665    buttonLast.setToolTipText("Play Previous Song In Playlist");
3666    buttonLast.setBorder(BorderFactory.createBevelBorder(
3667      BevelBorder.RAISED));
3668
3669    miniButtonLast.addActionListener(this);
3670    miniButtonLast.setIcon(iconMiniBack_);
3671    miniButtonLast.setOpaque(false);
3672    miniButtonLast.setBackground(buttonBackColour_);
3673    miniButtonLast.setPreferredSize(
3674      new Dimension(iconMiniBack_.getIconWidth(), iconMiniBack_.getIconHeight()));
3675    miniButtonLast.setToolTipText("Play Previous Song In Playlist");
3676    miniButtonLast.setBorder(BorderFactory.createBevelBorder(
3677      BevelBorder.RAISED));
3678
3679    buttonNext.addActionListener(this);
3680    buttonNext.setIcon(iconForward_);
3681    buttonNext.setOpaque(false);
3682    buttonNext.setBackground(buttonBackColour_);
3683    buttonNext.setPreferredSize(
3684      new Dimension(iconForward_.getIconWidth() + 5, iconForward_.getIconHeight() + 5));
3685    buttonNext.setToolTipText("Play Next Song In Playlist");
3686    buttonNext.setBorder(BorderFactory.createBevelBorder(
3687      BevelBorder.RAISED));
3688
3689    miniButtonNext.addActionListener(this);
3690    miniButtonNext.setIcon(iconMiniForward_);
3691    miniButtonNext.setOpaque(false);
3692    miniButtonNext.setBackground(buttonBackColour_);
3693    miniButtonNext.setPreferredSize(
3694      new Dimension(iconMiniForward_.getIconWidth(), iconMiniForward_.getIconHeight()));
3695    miniButtonNext.setToolTipText("Play Next Song In Playlist");
3696    miniButtonNext.setBorder(BorderFactory.createBevelBorder(
3697      BevelBorder.RAISED));
3698
3699    buttonPause.addActionListener(this);
3700    buttonPause.setIcon(iconPause_);
3701    buttonPause.setOpaque(false);
3702    buttonPause.setBackground(buttonBackColour_);
3703    buttonPause.setPreferredSize(
3704      new Dimension(iconPause_.getIconWidth() + 5, iconPause_.getIconHeight() + 5));
3705    buttonPause.setToolTipText("Pause Play");
3706    buttonPause.setEnabled(false);
3707    buttonPause.setBorder(BorderFactory.createBevelBorder(
3708      BevelBorder.RAISED));
3709
3710    miniButtonPause.addActionListener(this);
3711    miniButtonPause.setIcon(iconMiniPause_);
3712    miniButtonPause.setOpaque(false);
3713    miniButtonPause.setBackground(buttonBackColour_);
3714    miniButtonPause.setPreferredSize(
3715      new Dimension(iconMiniPause_.getIconWidth(), iconMiniPause_.getIconHeight()));
3716    miniButtonPause.setToolTipText("Pause Play");
3717    miniButtonPause.setEnabled(false);
3718    miniButtonPause.setBorder(BorderFactory.createBevelBorder(
3719      BevelBorder.RAISED));
3720
3721    buttonLoveLastfmTrack.setIcon(iconLoveTrack_);
3722    buttonLoveLastfmTrack.setToolTipText("Love Current Last.FM Track");
3723    buttonLoveLastfmTrack.setPreferredSize(
3724      new Dimension(iconLoveTrack_.getIconWidth() + 5, iconLoveTrack_.getIconHeight() + 5));
3725    buttonLoveLastfmTrack.setBorder(BorderFactory.createBevelBorder(
3726      BevelBorder.RAISED));
3727
3728    buttonAddUrlToPlaylist.setIcon(iconAddUrl_);
3729    buttonAddUrlToPlaylist.setToolTipText("Add A URL Song To The Playlist");
3730    buttonAddUrlToPlaylist.setPreferredSize(
3731      new Dimension(iconAddUrl_.getIconWidth() + 5, iconAddUrl_.getIconHeight() + 5));
3732    buttonAddUrlToPlaylist.setBorder(BorderFactory.createBevelBorder(
3733      BevelBorder.RAISED));
3734
3735    buttonAddToPlaylist.setIcon(iconAdd_);
3736    buttonAddToPlaylist.setToolTipText("Add A Song File To The Playlist");
3737    buttonAddToPlaylist.setPreferredSize(
3738      new Dimension(iconAdd_.getIconWidth() + 5, iconAdd_.getIconHeight() + 5));
3739    buttonAddToPlaylist.setBorder(BorderFactory.createBevelBorder(
3740      BevelBorder.RAISED));
3741
3742    buttonDeleteFromPlaylist.setIcon(iconDelete_);
3743    buttonDeleteFromPlaylist.setToolTipText("Remove A Song From The Playlist");
3744    buttonDeleteFromPlaylist.setPreferredSize(
3745      new Dimension(iconDelete_.getIconWidth() + 5, iconDelete_.getIconHeight() + 5));
3746    buttonDeleteFromPlaylist.setBorder(BorderFactory.createBevelBorder(
3747      BevelBorder.RAISED));
3748
3749    buttonRefreshPlaylist.setIcon(iconRefresh_);
3750
3751    buttonRefreshPlaylist.setToolTipText("Refresh the Playlist from the Directory");
3752    buttonRefreshPlaylist.setPreferredSize(
3753      new Dimension(iconRefresh_.getIconWidth() + 5, iconRefresh_.getIconHeight() + 5));
3754    buttonRefreshPlaylist.setBorder(BorderFactory.createBevelBorder(
3755      BevelBorder.RAISED));
3756
3757    miniButtonView_.addActionListener(this);
3758    miniButtonView_.setIcon(iconMiniView_);
3759    miniButtonView_.setToolTipText("Toggle Mini View");
3760    miniButtonView_.setPreferredSize(new Dimension(10, 10));
3761
3762    miniButtonClose_.addActionListener(this);
3763    miniButtonClose_.setIcon(iconMiniClose_);
3764    miniButtonClose_.setToolTipText("Close jOggPlayer");
3765    miniButtonClose_.setPreferredSize(
3766      new Dimension(iconMiniClose_.getIconWidth(), iconMiniClose_.getIconHeight()));
3767
3768    //miniDragButton.addActionListener(dragMiniViewMotionListener);
3769
3770    checkBoxLoop.setSelected(true);
3771    checkBoxLoop.setFont(new Font(checkBoxLoop.getFont().getFontName(),checkBoxLoop.getFont().getStyle(),uiFontSize_));
3772    checkBoxLoop.setBorderPainted(false);
3773    checkBoxLoop.setContentAreaFilled(false);
3774    checkBoxLoop.setToolTipText("Automatically proceed to next song.");
3775
3776    checkBoxRandom.setFont(new Font(checkBoxRandom.getFont().getFontName(),checkBoxRandom.getFont().getStyle(),uiFontSize_));
3777    checkBoxRandom.setBorderPainted(false);
3778    checkBoxRandom.setContentAreaFilled(false);
3779    checkBoxRandom.setToolTipText("Play the playlist songs in a random order.");
3780
3781    checkBoxMiniView.setFont(new Font(checkBoxMiniView.getFont().getFontName(),checkBoxMiniView.getFont().getStyle(),uiFontSize_));
3782    checkBoxMiniView.setBorderPainted(false);
3783    checkBoxMiniView.setContentAreaFilled(false);
3784    checkBoxMiniView.setToolTipText("Show the MiniView.");
3785
3786    checkBoxPlaylist.setFont(new Font(checkBoxPlaylist.getFont().getFontName(),checkBoxPlaylist.getFont().getStyle(),uiFontSize_));
3787    checkBoxPlaylist.setBorderPainted(false);
3788    checkBoxPlaylist.setContentAreaFilled(false);
3789    checkBoxPlaylist.setToolTipText("Show the playlist panel.");
3790    checkBoxRecursePlaylist.setToolTipText("Recurse all subdirectories of the " +
3791      "selected directory to find Oggs.");
3792    checkBoxRecursePlaylist.setFont(new Font(checkBoxRecursePlaylist.getFont().getFontName(),checkBoxRecursePlaylist.getFont().getStyle(),uiFontSize_));
3793
3794
3795    //miniDragLabel.
3796    //miniDragButton.
3797
3798    buttonDeleteFromPlaylist.addActionListener(deleteSelectedSongActionListener);
3799    buttonAddToPlaylist.addActionListener(addSongActionListener);
3800    buttonAddUrlToPlaylist.addActionListener(addURLActionListener);
3801
3802    buttonLoveLastfmTrack.addActionListener(
3803      new ActionListener()
3804      {
3805        public void actionPerformed(ActionEvent e)
3806        {
3807          loveLastfmCurrentTrack();
3808        }
3809      }
3810      );
3811
3812    buttonRefreshPlaylist.addActionListener(
3813      new ActionListener()
3814      {
3815        public void actionPerformed(ActionEvent e)
3816        {
3817          //System.out.println("Into Refresh Playlist Action");
3818          String[] playListFileNames = PlayList.getPlaylistArray(initArgs_);
3819          playList = new PlayList(Util.getFileBaseURLs(playListFileNames));
3820          playList.sortSongs();
3821          playListComboBox.removeAllItems();
3822          String[] playListNames = playList.getSongFileNames();
3823          JCheckBox jc = null;
3824          for (int i = 0; i < playListNames.length; i++)
3825          {
3826            jc = new JCheckBox(playListNames[i], true);
3827            jc.setToolTipText(getSongCommentPopup(i));
3828            playListComboBox.addItem(jc);
3829          }
3830          playListComboBox.validate();
3831        }
3832      }
3833      );
3834
3835    muteButton_.addActionListener(
3836      new ActionListener()
3837      {
3838        public void actionPerformed(ActionEvent e)
3839        {
3840          if (mutedVolume_ != 0)
3841          {
3842            volumeSlider_.setValue(mutedVolume_);
3843            mutedVolume_ = 0;
3844            volumeSlider_.setEnabled(true);
3845            muteButton_.setToolTipText("Mute The Volume.");
3846            muteButton_.setIcon(iconVolOn_);
3847          }
3848          else
3849          {
3850            mutedVolume_ = volumeSlider_.getValue();
3851            volumeSlider_.setValue(0);
3852            volumeSlider_.setEnabled(false);
3853            muteButton_.setToolTipText("Un-Mute The Volume.");
3854            muteButton_.setIcon(iconVolOff_);
3855          }
3856        }
3857      }
3858    );
3859
3860    volumeSlider_.addChangeListener(
3861      new ChangeListener()
3862      {
3863        public void stateChanged(ChangeEvent e)
3864        {
3865          /*
3866           *  volume Adjust
3867           */
3868          currVolSetting_ = volumeSlider_.getValue();
3869          currentVolumeMultiplier_ = volumeMultiplier(currVolSetting_);
3870          if (currVolSetting_ == 11)
3871          {
3872            volumeSlider_.setToolTipText("<HTML><BODY>" +
3873              "Volume: This Player Goes To <B>11</B>" +
3874              "</body></html>");
3875          }
3876          else
3877          {
3878            volumeSlider_.setToolTipText("<HTML><BODY>" +
3879              "Volume: " + currVolSetting_ +
3880              "</body></html>");
3881          }
3882        }
3883      });
3884
3885    checkBoxPlaylist.addChangeListener(
3886      new ChangeListener()
3887      {
3888        public void stateChanged(ChangeEvent e)
3889        {
3890          /*
3891           *  Show or Hide the playlist
3892           */
3893          if (checkBoxPlaylist.isSelected() && !playListShowing_)
3894          {
3895            showPlaylistPanel(true);
3896          }
3897          else if (!checkBoxPlaylist.isSelected() && playListShowing_)
3898          {
3899            showPlaylistPanel(false);
3900          }
3901        }
3902      });
3903
3904    checkBoxMiniView.addChangeListener(
3905      new ChangeListener()
3906      {
3907        public void stateChanged(ChangeEvent e)
3908        {
3909          /*
3910           *  Show or Hide the miniView
3911           */
3912          if (checkBoxMiniView.isSelected() && !miniViewShowing_)
3913          {
3914            showMiniView(true);
3915            checkBoxMiniView.setSelected(false);
3916          }
3917          //else if ( checkBoxMiniView.isSelected() && miniViewShowing_ )
3918          //{
3919          //  showMiniView(false);
3920          //  checkBoxMiniView.setSelected(false);
3921          //}
3922        }
3923      });
3924
3925    MouseAdapter myButtonMouseAdapter =
3926      new MouseAdapter()
3927      {
3928        public void mouseEntered(MouseEvent e)
3929        {
3930          JButton but = (JButton) e.getSource();
3931          if (but.isEnabled())
3932          {
3933            but.setBorderPainted(true);
3934            but.validate();
3935          }
3936        }
3937
3938        public void mouseExited(MouseEvent e)
3939        {
3940          JButton but = (JButton) e.getSource();
3941          if (but.isEnabled())
3942          {
3943            but.setBorderPainted(false);
3944            but.validate();
3945          }
3946        }
3947
3948        public void mousePressed(MouseEvent e)
3949        {
3950          JButton but = (JButton) e.getSource();
3951          if (but.isEnabled())
3952          {
3953            but.setBorder(BorderFactory.createBevelBorder(
3954              BevelBorder.LOWERED));
3955            but.validate();
3956          }
3957        }
3958
3959        public void mouseReleased(MouseEvent e)
3960        {
3961          JButton but = (JButton) e.getSource();
3962          if (but.isEnabled())
3963          {
3964            but.setBorder(BorderFactory.createBevelBorder(
3965              BevelBorder.RAISED));
3966            but.validate();
3967          }
3968        }
3969      };
3970
3971    buttonRefreshPlaylist.addMouseListener(myButtonMouseAdapter);
3972    buttonAddUrlToPlaylist.addMouseListener(myButtonMouseAdapter);
3973    buttonAddToPlaylist.addMouseListener(myButtonMouseAdapter);
3974    buttonDeleteFromPlaylist.addMouseListener(myButtonMouseAdapter);
3975    button.addMouseListener(myButtonMouseAdapter);
3976    buttonPause.addMouseListener(myButtonMouseAdapter);
3977    buttonNext.addMouseListener(myButtonMouseAdapter);
3978    buttonLast.addMouseListener(myButtonMouseAdapter);
3979    miniButtonPlay.addMouseListener(myButtonMouseAdapter);
3980    miniButtonPause.addMouseListener(myButtonMouseAdapter);
3981    miniButtonNext.addMouseListener(myButtonMouseAdapter);
3982    miniButtonLast.addMouseListener(myButtonMouseAdapter);
3983    buttonLoveLastfmTrack.addMouseListener(myButtonMouseAdapter);
3984
3985    /*
3986     *  panel is the Main Holder Panel
3987     */
3988    /*
3989     *  It gets Split into 3 components Top, Body, Bottom
3990     */
3991    /*
3992     *  (bottom is for mini-layout
3993     */
3994    panel.add(headerPanel, BorderLayout.NORTH);
3995    panel.add(bodyPanel, BorderLayout.CENTER);
3996    //panel.add(miniViewPanel, BorderLayout.SOUTH); //holds the mini-view layout
3997    // not initially shown
3998
3999    /*
4000     *  The Body holds the volume and the main area
4001     */
4002    bodyPanel.add(leftPanel, BorderLayout.WEST);
4003    bodyPanel.add(innerPanel, BorderLayout.CENTER);
4004    //    bodyPanel.add(rightPanel);
4005
4006    leftPanel.add(volumeSlider_, BorderLayout.CENTER);
4007    leftPanel.add(muteButton_, BorderLayout.SOUTH);
4008
4009    /*
4010     *  innerPanel holds the display area and the controls
4011     */
4012    innerPanel.add(innerHeaderPanel);
4013    innerPanel.add(displayPanel);
4014    innerPanel.add(controlPanel);
4015
4016    /*
4017     *  The Following holds the Playlist and is controlled by a checkbox
4018     */
4019    //    innerPanel.add(Box.createVerticalGlue());
4020    //    innerPanel.add(innerFooterPanel);
4021
4022    displayPanel.add(innerDisplayPanel, BorderLayout.CENTER);
4023    displayPanel.add(songProgress, BorderLayout.SOUTH);
4024    displayPanel.addMouseListener(popupListener_);
4025
4026    controlPanel.add(buttonPanel, BorderLayout.CENTER);
4027    controlPanel.add(checkPanel, BorderLayout.SOUTH);
4028
4029    innerDisplayPanel.add(innerLeftDisplayPanel, BorderLayout.WEST);
4030    innerDisplayPanel.add(innerRightDisplayPanel, BorderLayout.CENTER);
4031    //innerDisplayPanel.add(Box.createGlue());
4032
4033    innerLeftDisplayPanel.add(artistLabel);
4034    innerLeftDisplayPanel.add(titleLabel);
4035    //innerLeftDisplayPanel.add(Box.createVerticalStrut(5));
4036    innerLeftDisplayPanel.add(timeLabel);
4037
4038    innerRightDisplayPanel.add(artistLabelValue);
4039    innerRightDisplayPanel.add(titleLabelValue);
4040    //innerRightDisplayPanel.add(Box.createVerticalStrut(5));
4041    innerRightDisplayPanel.add(timeLabelValue);
4042
4043    /*
4044     *  Button Panel uses the default FlowLayout
4045     */
4046    buttonPanel.add(buttonLast);
4047    buttonPanel.add(buttonPause);
4048    buttonPanel.add(button);
4049    buttonPanel.add(buttonNext);
4050
4051    /*
4052     *  MINI Button Panel uses the default FlowLayout
4053     */
4054    miniButtonPanel.add(miniButtonLast);
4055    miniButtonPanel.add(miniButtonPause);
4056    miniButtonPanel.add(miniButtonPlay);
4057    miniButtonPanel.add(miniButtonNext);
4058    //log_.debug("Adding checkBoxMiniView");
4059    //buttonPanel.add(checkBoxMiniView);
4060
4061    /*
4062     *  this uses a FlowLayout so everything stays in a line
4063     */
4064
4065    checkPanel.add(checkBoxLoop);
4066    checkPanel.add(checkBoxRandom);
4067    checkPanel.add(checkBoxPlaylist);
4068    if(!this.running_as_applet) checkPanel.add(checkBoxMiniView);
4069
4070    /*
4071     *  this is the playlist panel area
4072     */
4073    KPanel tempP = new KPanel(new BorderLayout(0, 0));
4074    tempP.add(playListComboBox, BorderLayout.NORTH);
4075    innerFooterPanel.add(innerPlaylistPanel, BorderLayout.NORTH);
4076    innerFooterPanel.add(tempP, BorderLayout.SOUTH);
4077    innerFooterPanel.addMouseListener(popupListener_);
4078    tempP.addMouseListener(popupListener_);
4079
4080    innerPlaylistPanel.add(checkBoxRecursePlaylist);
4081    innerPlaylistPanel.add(buttonDeleteFromPlaylist);
4082    innerPlaylistPanel.add(buttonAddToPlaylist);
4083    innerPlaylistPanel.add(buttonAddUrlToPlaylist);
4084    innerPlaylistPanel.add(buttonRefreshPlaylist);
4085    innerPlaylistPanel.add(buttonLoveLastfmTrack);
4086
4087    /*
4088     * Mini View Window dressing
4089     */
4090    miniDragButton.setMaximumSize(new Dimension(500, 16));
4091    miniDragButton.setBorder(BorderFactory.createRaisedBevelBorder());
4092    //new emptyBorder(0,0,0,0));
4093    //miniDragButton.setBorder(new EmptyBorder(0,0,0,0));
4094    miniDragButton.setBorderPainted(true);
4095    miniDragButton.add(miniDragLabel);
4096    //miniDragButton.setPreferredSize(new Dimension(64,16));
4097    miniButtonView_.setPreferredSize(new Dimension(16, 16));
4098    miniButtonClose_.setPreferredSize(new Dimension(16, 16));
4099    miniButtonView_.setBorder(new EmptyBorder(0,0,0,0));
4100    miniButtonClose_.setBorder(new EmptyBorder(0,0,0,0));
4101    miniButtonView_.setBorderPainted(false);
4102    miniButtonClose_.setBorderPainted(false);
4103    KPanel miniViewClosePanel = new KPanel();
4104    miniViewClosePanel.setLayout(new FlowLayout(FlowLayout.CENTER,0,0));
4105      //new BoxLayout(miniViewClosePanel, BoxLayout.X_AXIS));
4106    miniViewClosePanel.setBorder(new EmptyBorder(0,0,0,0));
4107    miniViewClosePanel.add(miniButtonView_);
4108    miniViewClosePanel.add(miniButtonClose_);
4109    miniViewWindowControlPanel.setBorder(new EmptyBorder(0,0,0,0));
4110    miniViewWindowControlPanel.add(miniDragButton, BorderLayout.CENTER);
4111    miniViewWindowControlPanel.add(miniViewClosePanel, BorderLayout.EAST);
4112    miniViewPanel.add(miniTimeLabelValue);
4113    miniViewPanel.add(miniButtonPanel);
4114    //miniViewPanel.add(miniViewWindowControlPanel);
4115    miniViewPanel.setDoubleBuffered(true);
4116    miniDragButton.setDoubleBuffered(true);
4117    dragableMiniViewPanel.setDoubleBuffered(true);
4118    miniTimeLabelValue.setDoubleBuffered(true);
4119    miniViewPanel.setDoubleBuffered(true);
4120    miniViewWindowControlPanel.setDoubleBuffered(true);
4121    miniButtonClose_.setDoubleBuffered(true);
4122    miniButtonView_.setDoubleBuffered(true);
4123    miniTimeLabelValue.addMouseListener(popupListener_);
4124    miniViewPanel.addMouseListener(popupListener_);
4125    miniDragButton.addMouseListener(miniViewMouseListener);
4126    miniDragButton.addMouseMotionListener(dragMiniViewMotionListener);
4127    dragableMiniViewPanel.add(miniViewWindowControlPanel, BorderLayout.CENTER);
4128    dragableMiniViewPanel.add(miniViewPanel, BorderLayout.SOUTH);
4129    popUpWin_.getContentPane().add(dragableMiniViewPanel);
4130
4131    // Add a listener to the display area so we can deleay the tool tip
4132    // dismiss delay time
4133    MouseAdapter myDisplayMouseAdapter =
4134      new MouseAdapter()
4135      {
4136        int prevDismissDelay = 200;
4137        ToolTipManager toolTipMgr = ToolTipManager.sharedInstance();
4138        public void mouseEntered(MouseEvent e)
4139        {
4140          // last lets slow down the ToolTipText dismissDelay
4141          // so the user can read it
4142          prevDismissDelay = toolTipMgr.getDismissDelay();
4143          toolTipMgr.setDismissDelay(songInfoDisplayDismissDelay_);
4144        }
4145
4146        public void mouseExited(MouseEvent e)
4147        {
4148          // now put it back to the normal delay for all the other components
4149          toolTipMgr.setDismissDelay(prevDismissDelay);
4150        }
4151      };
4152    displayPanel.addMouseListener(myDisplayMouseAdapter);
4153    miniTimeLabelValue.addMouseListener(myDisplayMouseAdapter);
4154    miniDragButton.addMouseListener(myDisplayMouseAdapter);
4155
4156    new FileDrop(playListComboBox, fDropListener);
4157
4158    if(!running_as_applet && showPlaylistOnStart_)
4159    {
4160      showPlaylistPanel(true);
4161      checkBoxPlaylist.setSelected(true);
4162    }
4163    else
4164    {
4165      checkBoxPlaylist.setSelected(false);
4166    }
4167    setColours();
4168
4169    log_.endMethod();
4170  }
4171
4172
4173  private void autoPlay()
4174  {
4175    if (!playList.isEmpty())
4176    {
4177      int currentItemIndex = playListComboBox.getSelectedIndex();
4178      int numSongs = playListComboBox.getItemCount();
4179      if (currentItemIndex < 0)
4180        currentItemIndex = 0;
4181      button.setIcon(iconStop_);
4182      buttonPause.setEnabled(true);
4183      button.setToolTipText("Stop Current Song");
4184      miniButtonPlay.setIcon(iconMiniStop_);
4185      miniButtonPause.setEnabled(true);
4186      miniButtonPlay.setToolTipText("Stop Current Song");
4187      log_.debug("\nAuto Play Starting");
4188      System.out.println("Auto Play Starting");
4189      if (checkBoxLoop.isSelected())
4190      {
4191        log_.debug("\nLooping Songs");
4192        System.out.println("\nLooping "+numSongs+" Songs");
4193        //checkBoxLoop.setEnabled(false);
4194        looping_ = true;
4195        if (currentItemIndex > 0)
4196        {
4197          currentItemIndex--;
4198        }
4199        else
4200        {
4201          currentItemIndex = numSongs - 1;
4202        }
4203        playListComboBox.setSelectedIndex(currentItemIndex);
4204        String item = (String) (((JCheckBox) playListComboBox.
4205          getSelectedItem()).getText());
4206        //log_.debug("\nPlay Button on item " +currentItemIndex + " " +item);
4207        playing_ = false; //playerThread_ = null;
4208        looperThread_ = new Thread(loopingRunnable_);
4209        looperThread_.start();
4210      }
4211      else
4212      {
4213        JCheckBox selectedCheckbox = (JCheckBox)playListComboBox.getSelectedItem();
4214        if (selectedCheckbox != null)
4215        {
4216          String item = (String) (selectedCheckbox.getText());
4217          System.out.println("Trying to Auto Play Song"+item);
4218          tryPlay(playList.getURL(item));
4219        }
4220      }
4221    }
4222  }
4223
4224  /**
4225   *  Does the gruntwork to get the proxy properties set.
4226   **/
4227
4228  public void initProxy()
4229  {
4230    // Set up the proxy settings if needed
4231    Properties sysProps = System.getProperties();
4232    String tmpUseproxy  = sysProps.getProperty("proxySet");
4233    if (tmpUseproxy != null && !tmpUseproxy.equals(""))
4234      areWeUsingProxy_ = (tmpUseproxy.toLowerCase().equals("true")?true:false);
4235
4236    if (areWeUsingProxy_)
4237    {
4238      System.out.println("Initializing the proxy settings");
4239      // check if the user had something defined in the Sys Props via the cmdline.
4240      String tmpUser  = sysProps.getProperty("http.proxyUser");
4241      String tmpPass  = sysProps.getProperty("http.proxyPassword");
4242      String tmpHost  = sysProps.getProperty("http.proxyHost");
4243      String tmpPort  = sysProps.getProperty("http.proxyPort");
4244
4245      if (tmpUser != null && !tmpUser.equals(""))
4246        proxyUsername_ = tmpUser;
4247      if (tmpPass != null && !tmpPass.equals(""))
4248        proxyPassword_ = tmpPass;
4249      if (tmpHost != null && !tmpHost.equals(""))
4250        proxyHost_ = tmpHost;
4251      if (tmpPort != null && !tmpPort.equals(""))
4252        proxyPort_ = tmpHost;
4253
4254      if (useProxyAuthentication_)
4255      {
4256        System.out.println("Authenticating the proxy.");
4257        Authenticator.setDefault(new FirewallAuthenticator(proxyUsername_,
4258                                                           proxyPassword_));
4259      }
4260      sysProps.put("proxySet", "true");
4261      sysProps.put("http.proxyHost", proxyHost_);
4262      sysProps.put("http.proxyPort", proxyPort_);
4263      sysProps.put("noProxy", proxyNoProxy_);
4264    }
4265
4266  }
4267
4268
4269  /**
4270   * The main program for the jOggPlayer class
4271   *
4272   * @param arg  The command line arguments
4273   */
4274  public static void main(String[] arg)
4275  {
4276    System.out.println("Starting jOggPlayer with logging going to:" +logFile_);
4277    log_ = Log.createLog(Log.NONE, logFile_);
4278    String splashGraphic = "/images/dont_pan.jpg";
4279    Image splashImage = Util.loadImage(splashGraphic);
4280    Panel p = new Panel();
4281    /*
4282     *  p.setBorder(new CompoundBorder(
4283     *  new MatteBorder(1,1,1,1,Color.black),
4284     *  new EmptyBorder(12,12,12,12)));
4285     */
4286    p.setBackground(new Color(210, 210, 210));
4287    Label l = new Label("Please wait while loading.");
4288    p.add(l);
4289    Splash frame = new Splash(splashImage, 5000, p);
4290    //Splash splash = new Splash(splashGraphic, 5000, (Panel)p);
4291
4292    appCodeBase_ = Util.getFileBaseURL(USER_DIR);
4293    appFrame_ = new JFrame();
4294    Util.setIconForApp(appFrame_,"/images/jOggPlayerIcon.jpg");
4295    appFrame_.getContentPane().setLayout(new BorderLayout());
4296    appFrame_.setTitle(APP_NAME + " - No Songs Currently Playing");
4297//    appFrame_.setIconImage(new ImageIcon(IMAGE_DIR+"Applet24.gif","jOggPlayer Player");
4298    //Add listener to components that can bring up popup menus.
4299    //appFrame_.addMouseListener(popupListener_);
4300    applicationPlayer = new jOggPlayer(arg);
4301    applicationPlayer.running_as_applet = false;
4302    running_as_applet = false;
4303    applicationPlayer.init();
4304    applicationPlayer.start();
4305    appFrame_.addWindowListener(
4306      new WindowAdapter()
4307      {
4308        public void windowClosing(WindowEvent e)
4309        {
4310          applicationPlayer.stop();
4311          applicationPlayer.log_.close();
4312          applicationPlayer = null;
4313          System.exit(0);
4314        }
4315      });
4316
4317    appFrame_.getContentPane().add(applicationPlayer.panel);
4318    appFrame_.pack();
4319    if(xpos == -1)
4320    {
4321      KiwiUtils.centerWindow(appFrame_);
4322      appXpos = appFrame_.getX();
4323      appYpos = appFrame_.getY();
4324    }
4325    else
4326    {
4327      appFrame_.setLocation(appXpos,appYpos);
4328    }
4329    if (showMiniViewOnStart_)
4330      showMiniView(true);
4331    else
4332    {
4333      appFrame_.toFront();
4334      frame.finishSplash();
4335      appFrame_.setVisible(true);
4336      frameInitSize_ = appFrame_.getSize();
4337      frameCurrentSize_ = frameInitSize_;
4338      //appFrame_.setResizable(false);
4339      appFrame_.repaint();
4340    }
4341
4342
4343    // now start a song if requested to AutoStart
4344    if (autoPlayOnStart_)
4345    {
4346      applicationPlayer.autoPlay();
4347    }
4348    //log_.endMethod();
4349  }
4350
4351
4352  /**
4353   * A helper method that initializes the required class vars. This gets called
4354   * by this class running as an applet.
4355   */
4356  public void init()
4357  {
4358    final String methodName = className_ + ": init";
4359    log_.startMethod(methodName);
4360    System.out.println("Init...");
4361
4362    String s = null;
4363    String cbStr = null;
4364
4365    // Load applet parms
4366    if(running_as_applet)
4367    {
4368      log_.debug("Loading applet parms:");
4369      s = getParameter("jOggPlayer.playlist");
4370      cbStr = getParameter("jOggPlayer.codebase");
4371      log_.debug("Playlist:"+s);
4372      log_.debug("codebase:"+cbStr);
4373    }
4374    else
4375    {
4376      cbStr = "file:////" + USER_DIR;
4377    }
4378    // Load up the config parms from the ini file
4379    // first of all we load an existing file
4380    File configFile = new File(configFileName_);
4381    System.out.println("Getting config from file "+configFileName_+ " "+configFile.exists());
4382
4383    if (configFile.exists())
4384    {
4385      // load the file
4386      try
4387      {
4388        cfgmgr_.load(configFile);
4389        loadConfigs();
4390      }
4391      catch (Exception e)
4392      {
4393        // ups, something went wrong and we have to stop here
4394        log_.minor("Can't Load config file.",e);
4395      }
4396    }
4397    else
4398    {
4399      // Create a new Config file
4400      createConfigs();
4401    }
4402    initProxy();
4403
4404    if (cbStr != null)
4405      try
4406      {
4407       codeBase_ = new URL(cbStr);
4408      }
4409      catch (MalformedURLException ee)
4410      {
4411        log_.minor("codeBase_ crap out", ee);
4412      }
4413    if (s != null)
4414    {
4415      playListFilename_ = s;
4416    }
4417
4418    /* register with last.fm  */
4419    if (lastFM_userId!=null && !lastFM_userId.equals(""))
4420      sc_ = handshakeWithLastfm(lastFM_userId);
4421
4422
4423
4424    String[] playListFileNames = PlayList.getPlaylistArray(initArgs_);
4425    System.out.print("Loading Playlist with "+playListFileNames.length+" songs...");
4426    playList = new PlayList(Util.getFileBaseURLs(playListFileNames));
4427    playList.sortSongs();
4428    System.out.println(" DONE!");
4429    if (playList.isEmpty())
4430    {
4431      URL playlistURL = null;
4432      if (running_as_applet)
4433      {
4434        URL cb = null;
4435        try
4436        {
4437          cb = getCodeBase();
4438          playlistURL = new URL(playListFilename_);
4439        }
4440        catch (MalformedURLException ee)
4441        {
4442          log_.minor("The Playlist Filename has some errors. " +
4443            "Please check the filename:\n" + playListFilename_, ee);
4444        }
4445        catch (Exception ex)
4446        {
4447          log_.minor("Error Obtaining codebase()",ex);
4448        }
4449      }
4450      else
4451      {
4452        System.out.println("Opening playlist File" +
4453          playListFilename_);
4454        playlistURL = Util.getFileBaseURL(playListFilename_);
4455      }
4456      if (playlistURL != null)
4457        playList.loadPlaylist(playlistURL);
4458    }
4459    if (loadTextureNames() != null)
4460      availableTextureNames_ = loadTextureNames();
4461    loadIconImages();
4462    initUI();
4463    panel.addMouseListener(popupListener_);
4464    getContentPane().add(panel);
4465
4466    /* Now handshake with last.fm */
4467    if (lastFM_userId!=null && !lastFM_userId.equals(""))
4468      sc_ = handshakeWithLastfm(lastFM_userId);
4469
4470    log_.endMethod();
4471  }
4472
4473
4474  /**
4475   * The applet start *
4476   */
4477  public void start()
4478  {
4479    final String methodName = className_ + ": start";
4480    log_.startMethod(methodName);
4481    System.out.println("Start...");
4482    setVisible(true);
4483    repaint();
4484
4485    log_.endMethod();
4486  }
4487
4488  /**
4489   * The Runnable to do the actual playing of the song. All the rest of this class
4490   * is fluff to get to this point [:)] . This code was developed by the jCraft
4491   * group.
4492   *
4493   */
4494  public void run()
4495  {
4496    final String methodName = className_ + ": run()";
4497    log_.startMethod(methodName);
4498    init_jorbis();
4499    Thread me = Thread.currentThread();
4500    me.setPriority(Thread.MAX_PRIORITY);
4501    progressCount_ = 0;
4502    int index = 0;
4503    boolean streamStillHasData = true;
4504    try
4505
4506    {
4507      while (playing_ && streamStillHasData)
4508      {
4509        int eos = 0;
4510        System.out.println("Init file...");
4511
4512        index = oggSyncState_.buffer(bufferSize_);
4513        buffer = oggSyncState_.data;
4514
4515        bytes = readFromStream(buffer, index, bufferSize_);
4516        if (bytes == -1)
4517        {
4518          streamStillHasData = false;
4519          System.out.println("Cannot get any data from selected Ogg bitstream.");
4520          log_.minor("Cannot get any data from selected Ogg bitstream. ");
4521          break;
4522        }
4523        oggSyncState_.wrote(bytes);
4524        if (oggSyncState_.pageout(oggPage_) != 1)
4525        {
4526          streamStillHasData = false;
4527          if (bytes < bufferSize_)
4528          {
4529            log_.debug("No more data");
4530            break;
4531          }
4532          log_.minor("Input does not appear to be an Ogg bitstream.");
4533          System.out.println("Input does not appear to be an Ogg bitstream.");
4534          break;
4535        }
4536        oggStreamState_.init(oggPage_.serialno());
4537        vorbisInfo.init();
4538        vorbisComment.init();
4539        if (oggStreamState_.pagein(oggPage_) < 0)
4540        {
4541          // error; stream version mismatch perhaps
4542          log_.minor("Error reading first page of Ogg bitstream data.");
4543          System.out.println("Error reading first page of Ogg bitstream data.");
4544          break;
4545        }
4546        int tmpInt = oggStreamState_.packetout(oggPacket_);
4547        if (tmpInt != 1)
4548        {
4549          // no page? must not be vorbis
4550          log_.minor("Error reading initial header packet. ("+tmpInt + ")");
4551          System.out.println("Error reading initial header packet. ("+tmpInt + ")");
4552          break;
4553        }
4554        tmpInt = vorbisInfo.synthesis_headerin(vorbisComment, oggPacket_);
4555        if (tmpInt < 0)
4556        {
4557          // error case; not a vorbis header
4558          log_.minor("This Ogg bitstream does not contain Vorbis audio data. ("+tmpInt + ")");
4559          System.out.println("This Ogg bitstream does not contain Vorbis audio data. ("+tmpInt + ")");
4560          break;
4561        }
4562        System.out.println("Valid Ogg bitstream.");
4563        log_.debug("Valid Ogg bitstream.");
4564
4565        int i = 0;
4566        while (i < 2)
4567        {
4568          while (i < 2)
4569          {
4570            int result = oggSyncState_.pageout(oggPage_);
4571            if (result == 0)
4572            {
4573              break;
4574            } // Need more data
4575            if (result == 1)
4576            {
4577              oggStreamState_.pagein(oggPage_);
4578              while (i < 2)
4579              {
4580                result = oggStreamState_.packetout(oggPacket_);
4581                if (result == 0)
4582                {
4583                  break;
4584                }
4585                if (result == -1)
4586                {
4587                  log_.minor("Corrupt secondary header.  Exiting.");
4588                  return;
4589                }
4590                vorbisInfo.synthesis_headerin(vorbisComment, oggPacket_);
4591                i++;
4592              }
4593            }
4594          }
4595          index = oggSyncState_.buffer(bufferSize_);
4596          buffer = oggSyncState_.data;
4597          bytes = readFromStream(buffer, index, bufferSize_);
4598          if (bytes == -1)
4599          {
4600            break;
4601          }
4602          if (bytes == 0 && i < 2)
4603          {
4604            log_.minor("End of file before finding all Vorbis  headers!");
4605            return;
4606          }
4607          oggSyncState_.wrote(bytes);
4608        }
4609
4610        byte[][] ptr = vorbisComment.user_comments;
4611        String currComment = "";
4612        int sel = playListComboBox.getSelectedIndex();
4613        String tmpUrlStr = playList.getSongUrl(sel).toString();
4614        int endIndx = tmpUrlStr.toString().lastIndexOf('/');
4615        int startIndx = tmpUrlStr.toString().indexOf('/')+1;
4616        if (endIndx == -1) endIndx = startIndx;
4617        String urlBase = tmpUrlStr.substring(startIndx,endIndx);
4618        artistLabelValue.setText(urlBase);
4619        String selSongName = playList.getSongName(sel);
4620        titleLabelValue.setText(selSongName);
4621        miniDragLabel.setText(selSongName);
4622        songComments_.clear();
4623        for (int j = 0; j < ptr.length; j++)
4624        {
4625          if (ptr[j] == null)
4626          {
4627            break;
4628          }
4629          currComment = (new String(ptr[j], 0, ptr[j].length - 1)).trim();
4630          songComments_.add(currComment);
4631
4632          String tmpStr = playList.getSongArtist(sel);
4633          if (!tmpStr.equals("")) artistLabelValue.setText(tmpStr);
4634          tmpStr = playList.getSongTitle(sel);
4635          if (!tmpStr.equals(""))
4636          {
4637            titleLabelValue.setText(tmpStr);
4638            miniDragLabel.setText(tmpStr);
4639          }
4640
4641          if (currComment.toUpperCase().startsWith("ARTIST"))
4642          {
4643            artistLabelValue.setText(currComment.substring(7));
4644            playList.setArtist(sel,currComment.substring(7));
4645          }
4646          else if (currComment.toUpperCase().startsWith("TITLE"))
4647          {
4648            titleLabelValue.setText(currComment.substring(6));
4649            miniDragLabel.setText(currComment.substring(6));
4650            playList.setTitle(sel,currComment.substring(6));
4651          }
4652          //System.out.println("Comment: " + currComment);
4653        }
4654        displayPanel.validate();
4655        //currComment = "Bitstream: " + vorbisInfo.channels + " channel," + vorbisInfo.rate + "Hz";
4656        currComment = "Bitstream: " + playList.getSongChannels(sel) + " channel," +
4657                       playList.getSongBitrate(sel) + "Hz";
4658        songComments_.add(currComment);
4659        //System.out.println(currComment);
4660        currComment = "Encoded by: " + new String(vorbisComment.vendor, 0,
4661          vorbisComment.vendor.length - 1);
4662        songComments_.add(currComment);
4663        //System.out.println(currComment);
4664        updateDisplayPopup();
4665        convsize = bufferSize_ / vorbisInfo.channels;
4666        vorbisDspState.synthesis_init(vorbisInfo);
4667        vorbisBlock.init(vorbisDspState);
4668        double[][][] _pcm = new double[1][][];
4669        float[][][] _pcmf = new float[1][][];
4670        int[] _index = new int[vorbisInfo.channels];
4671        getOutputLine(vorbisInfo.channels, vorbisInfo.rate);
4672        startTimer();
4673
4674        /* got all the headers and comments so start Playing the song */
4675        lastFM_songStartTime_=new Date();
4676        log_.debug("lastFMConnected_ = "+lastFMConnected_);
4677        System.out.println("lastFMConnected_ = "+lastFMConnected_);
4678        if (lastFMConnected_)
4679        {
4680          try
4681          {
4682          /*  Tell last.fm Whats currently Playing */
4683          System.out.println("Sending Playing Song Info to Last.fm: "+playList.getSongArtist(sel)+" "+
4684                                 playList.getSongTitle(sel)+" "+
4685                                 playList.getSongAlbum(sel)+" 0 "+
4686                                 playList.getTrackNumber(sel));
4687          if(USE_LASTFM_2)
4688          {
4689            scrobbleResult_ = Track.updateNowPlaying(playList.getSongArtist(sel),
4690                                                     playList.getSongTitle(sel),
4691                                                     getLastFMSession()); //  lastFMSession_);
4692            log_.debug("lastFM nowPlaying: " + (scrobbleResult_.isSuccessful() && !scrobbleResult_.isIgnored()));
4693            System.out.println("lastFM nowPlaying: " + (scrobbleResult_.isSuccessful() && !scrobbleResult_.isIgnored()));
4694          }
4695          else
4696          {
4697            resp_ = sc_.nowPlaying(playList.getSongArtist(sel),
4698                                   playList.getSongTitle(sel),
4699                                   playList.getSongAlbum(sel),
4700                                   240, // this is supposed to be the sondlenght in seconds - We don't know this.  Timer Thread does
4701                                   playList.getTrackNumber(sel));
4702            if (resp_ !=null && resp_.ok())
4703            {
4704              log_.debug("Sending nowPlaying Succeeded for user: "+lastFM_userId);
4705              System.out.println("Sending nowPlaying Succeeded for user: "+lastFM_userId);
4706            }
4707            else
4708            {
4709              if (resp_ != null)
4710              {
4711                log_.minor("Sending nowPlaying Failed for user: "+lastFM_userId + " - ("+
4712                          getLastfmErrorType(resp_.getStatus()) +") "+resp_.getMessage());
4713                System.out.println("Re-Sending nowPlaying Failed for user: "+lastFM_userId + " - ("+
4714                          getLastfmErrorType(resp_.getStatus()) +") "+resp_.getMessage());
4715                sc_ = handshakeWithLastfm(lastFM_userId);
4716                System.out.println("Re-Sending Playing Song Info to Last.fm: "+playList.getSongArtist(sel)+" "+
4717                                       playList.getSongTitle(sel)+" "+
4718                                       playList.getSongAlbum(sel)+" 0 "+
4719                                       playList.getTrackNumber(sel));
4720                resp_ = sc_.nowPlaying(playList.getSongArtist(sel),
4721                                       playList.getSongTitle(sel),
4722                                       playList.getSongAlbum(sel),
4723                                       240, // this is supposed to be the sondlenght in seconds - We don't know this.Timer Thread does
4724                                       playList.getTrackNumber(sel));
4725                if (resp_ !=null && resp_.ok())
4726                {
4727                  log_.debug("Re-Sending nowPlaying Succeeded for user: "+lastFM_userId);
4728                  System.out.println("Re-Sending nowPlaying Succeeded for user: "+lastFM_userId);
4729                }
4730              }
4731            }
4732          }
4733
4734          }
4735          catch (IOException ioEx)
4736          {
4737            log_.minor("Could NOT send now playing to last.fm",ioEx);
4738          }
4739        }
4740
4741        while (eos == 0)
4742        {
4743          while (eos == 0)
4744          {
4745            if (!playing_ || playerThread_ == null)
4746            {
4747              System.err.println("bye.");
4748              timerRunning_ = false;
4749              try
4750              {
4751                //outputLine.drain();
4752                //outputLine.stop();
4753                //outputLine.close();
4754                oggBitStream_.close();
4755              }
4756              catch (Exception ee)
4757              {
4758              }
4759              button.setIcon(iconPlay_);
4760              miniButtonPlay.setIcon(iconMiniPlay_);
4761              if (miniViewShowing_)
4762              {
4763                buttonPause.setEnabled(false);
4764              }
4765              else
4766              {
4767                miniButtonPause.setEnabled(false);
4768              }
4769
4770              /* Last.fm Song Submit */
4771              if (lastFMConnected_)
4772              {
4773                try
4774                {
4775                  //int playTime = (new Long(((new Date()).getTime() - lastFM_songStartTime_.getTime())/1000)).intValue();
4776                  int playTime =  timeWatcherThread_.getPlayTime()/1000;
4777                  if (playTime > 30 && ( songProgress.getPercentComplete() >0.50 || playTime >240) &&
4778                      !playList.getSongArtist(sel).equals("") &&
4779                      !playList.getSongTitle(sel).equals("") &&
4780                      !playList.getSongAlbum(sel).equals("")
4781                     )
4782                  {
4783                    System.out.println("Submitting: "+ playList.getSongArtist(sel)+" "+
4784                                       playList.getSongTitle(sel)+" "+playList.getSongAlbum(sel)+
4785                                       " played for:"+playTime+
4786                                       "sec. at " + lastFM_songStartTime_.getTime()/1000);
4787
4788                    if(USE_LASTFM_2)
4789                    {
4790
4791                       int now = (int) (System.currentTimeMillis() / 1000);
4792                       de.umass.lastfm.scrobble.ScrobbleData sd = new de.umass.lastfm.scrobble.ScrobbleData(playList.getSongArtist(sel),
4793                                                                                                              playList.getSongTitle(sel),
4794                                                                                                              now);
4795                       sd.setAlbum(playList.getSongAlbum(sel));
4796                       sd.setTrackNumber(playList.getTrackNumber(sel));
4797
4798                       ScrobbleResult result = Track.scrobble(sd, getLastFMSession());
4799
4800                      if (result != null)
4801                        System.out.println("Song Sumbitted: " + (result.isSuccessful() && !result.isIgnored()));
4802                      else
4803                      {
4804                        System.out.println("Sumbmit Failed --> (" +result.getErrorMessage());
4805                      }
4806                    }
4807                    else
4808                    {
4809                      resp_ = sc_.submit(playList.getSongArtist(sel),
4810                                         playList.getSongTitle(sel),
4811                                         playList.getSongAlbum(sel),
4812                                         playTime,
4813                                         playList.getTrackNumber(sel),
4814                                         Source.USER,
4815                                         lastFM_songStartTime_.getTime()/1000);
4816                      if (resp_!=null && resp_.ok())
4817                      {
4818                        System.out.println("Song Sumbitted");
4819                      }
4820                      else
4821                      {
4822                        if (resp_ != null)
4823                        {
4824                          System.out.println("Sumbmit Failed --> (" +getLastfmErrorType(resp_.getStatus()) +") "+resp_.getMessage());
4825                          sc_ = handshakeWithLastfm(lastFM_userId);
4826                          System.out.println("Re-Submitting: "+ playList.getSongArtist(sel)+" "+
4827                                             playList.getSongTitle(sel)+" "+playList.getSongAlbum(sel)+
4828                                             " played for:"+playTime+
4829                                             "sec. at " + lastFM_songStartTime_.getTime()/1000);
4830                          resp_ = sc_.submit(playList.getSongArtist(sel),
4831                                             playList.getSongTitle(sel),
4832                                             playList.getSongAlbum(sel),
4833                                             playTime,
4834                                             playList.getTrackNumber(sel),
4835                                             Source.USER,
4836                                             lastFM_songStartTime_.getTime()/1000);
4837                          if (resp_!=null && resp_.ok())
4838                          {
4839                            System.out.println("Song Sumbitted");
4840                          }
4841                        }
4842                      }
4843                    }
4844                  }
4845                  else
4846                  {
4847                    System.out.println("Song NOT submitted because it was too short or did not play long enough or did not have songInfo");
4848                    log_.debug("Song NOT submitted because it was too short or did not play long enough or did not have songInfo");
4849                  }
4850                }
4851                catch (IOException ioEx)
4852                {
4853                  log_.minor("Last.fm submit failed --> (" +getLastfmErrorType(resp_.getStatus()) +") "+resp_.getMessage() ,ioEx);
4854                }
4855              }
4856              /* Last.fm Song Submit */
4857
4858              return;
4859            }
4860            int result = oggSyncState_.pageout(oggPage_);
4861            if (result == 0)
4862            {
4863              break;
4864            } // need more data
4865            if (result == -1)
4866            { // missing or corrupt data at this page position
4867              System.err.println("Corrupt or missing data in bitstream; " +
4868                "continuing...");
4869            }
4870            else
4871            {
4872              oggStreamState_.pagein(oggPage_);
4873
4874              /* This is the endless Play song loop */
4875              /* ---------------------------------- */
4876              result = 1;
4877              while (playing_ && result!=0)
4878              {
4879                result = oggStreamState_.packetout(oggPacket_);
4880                //if (result == 0)
4881                //{
4882                //  break;
4883                //} // need more data
4884                if (result <1 ) //== -1)
4885                { // missing or corrupt data at this page position
4886                  // no reason to complain; already complained above
4887                }
4888                else // only if there is data
4889                {
4890                  // we have a packet.  Decode it
4891                  int samples;
4892                  if (vorbisBlock.synthesis(oggPacket_) == 0)
4893                  { // test for success!
4894                    vorbisDspState.synthesis_blockin(vorbisBlock);
4895                  }
4896
4897                  /* ******************************************   */
4898                  /* This is the Data Read and convert Block      */
4899                  /* ******************************************   */
4900                  // start sampling the data into _pcmf
4901                  while ((samples = vorbisDspState.synthesis_pcmout(_pcmf, _index)) > 0)
4902                  {   //samples holds the size of data in recent read
4903
4904                    //double[][] pcm = _pcm[0];  // not used  DELETE ME
4905                    float[][] pcmf = _pcmf[0];
4906                    boolean clipflag = false;
4907                    int bout = (samples < convsize ? samples : convsize);
4908                    double fVal = 0.0;
4909                    // convert doubles to 16 bit signed ints (host order) and interleave
4910                    for (i = 0; i < vorbisInfo.channels; i++)
4911                    {
4912                      int pointer = i * 2;
4913                      //int ptr=i;
4914                      int mono = _index[i];
4915                      for (int j = 0; j < bout; j++)
4916                      {
4917                        fVal = (float) pcmf[i][mono + j] * 32767.;
4918                        /*
4919                         *  volume Adjust
4920                         */
4921                        fVal = fVal * currentVolumeMultiplier_;
4922                        int val = (int) (fVal);
4923                        if (val > 32767)
4924                        {
4925                          val = 32767;
4926                          clipflag = true;
4927                        }
4928                        if (val < -32768)
4929                        {
4930                          val = -32768;
4931                          clipflag = true;
4932                        }
4933                        if (val < 0)
4934                        {
4935                          val = val | 0x8000;
4936                        }
4937                        convbuffer[pointer] = (byte) (val);
4938                        convbuffer[pointer + 1] = (byte) (val >>> 8);
4939                        pointer += 2 * (vorbisInfo.channels);
4940                      }
4941                    }
4942
4943                    // transfer the converted bytes to the output line
4944                    outputLine.write(convbuffer, 0, 2 * vorbisInfo.channels * bout);
4945                    vorbisDspState.synthesis_read(bout);
4946                  }
4947                  //Update the Progress Bar
4948                  songProgress.setValue(progressCount_);
4949
4950                  while (loopPaused_)
4951                  {
4952                    Util.sleep(200);
4953                  }
4954                } //valid packet processed
4955              } //// Endless Play Loop until playing_ stops us OR the ogg stream was empty
4956              if (oggPage_.eos() != 0)
4957              {
4958                eos = 1;
4959              }
4960            }
4961          }
4962          if (eos == 0)
4963          {
4964            index = oggSyncState_.buffer(bufferSize_);
4965            buffer = oggSyncState_.data;
4966            bytes = readFromStream(buffer, index, bufferSize_);
4967            if (bytes == -1)
4968            {
4969              System.out.println("Ogg Stream empty.");
4970              log_.debug("Ogg Stream empty.");
4971              streamStillHasData = false;
4972              eos = 1;
4973              //break;
4974            }
4975            else
4976            {
4977              oggSyncState_.wrote(bytes);
4978              if (bytes == 0)
4979              {
4980                log_.debug("No data left in Ogg Stream.");
4981                eos = 1;
4982              }
4983            }
4984          }
4985        }
4986        if (oggStreamState_!=null) oggStreamState_.clear();
4987        if (vorbisBlock!=null)vorbisBlock.clear();
4988        if (vorbisDspState!=null)vorbisDspState.clear();
4989        if (vorbisInfo!=null)vorbisInfo.clear();
4990      }
4991    }
4992    catch (Exception ex)
4993    {
4994      //System.out.println("Ogg Stream Exception. "+ex.getMessage());
4995      ex.printStackTrace();
4996      log_.debug("Ogg Stream Exception. "+ex.getMessage());
4997    }
4998
4999    /* Last.fm Song Submit */
5000    if (lastFMConnected_)
5001    {
5002      int sel = playListComboBox.getSelectedIndex();
5003      if (sel>=0)
5004      try
5005      {
5006        //int playTime = (new Long(((new Date()).getTime() - lastFM_songStartTime_.getTime())/1000)).intValue();
5007        int playTime =  timeWatcherThread_.getPlayTime()/1000;
5008        if (playTime > 30 && ( songProgress.getPercentComplete() >0.50 || playTime >240) &&
5009            !playList.getSongArtist(sel).equals("") &&
5010            !playList.getSongTitle(sel).equals("") &&
5011            !playList.getSongAlbum(sel).equals("")
5012           )
5013                  {
5014                    System.out.println("Submitting: "+ playList.getSongArtist(sel)+" "+
5015                                       playList.getSongTitle(sel)+" "+playList.getSongAlbum(sel)+
5016                                       " played for:"+playTime+
5017                                       "sec. at " + lastFM_songStartTime_.getTime()/1000);
5018
5019                    if(USE_LASTFM_2)
5020                    {
5021
5022                       int now = (int) (System.currentTimeMillis() / 1000);
5023                       de.umass.lastfm.scrobble.ScrobbleData sd = new de.umass.lastfm.scrobble.ScrobbleData(playList.getSongArtist(sel),
5024                                                                                                              playList.getSongTitle(sel),
5025                                                                                                              now);
5026                       sd.setAlbum(playList.getSongAlbum(sel));
5027                       sd.setTrackNumber(playList.getTrackNumber(sel));
5028
5029                       ScrobbleResult result = Track.scrobble(sd, getLastFMSession());
5030
5031                      if (result != null)
5032                        System.out.println("Song Sumbitted: " + (result.isSuccessful() && !result.isIgnored()));
5033                      else
5034                      {
5035                        System.out.println("Sumbmit Failed --> (" +result.getErrorMessage());
5036                      }
5037                    }
5038                    else
5039                    {
5040                      resp_ = sc_.submit(playList.getSongArtist(sel),
5041                                         playList.getSongTitle(sel),
5042                                         playList.getSongAlbum(sel),
5043                                         playTime,
5044                                         playList.getTrackNumber(sel),
5045                                         Source.USER,
5046                                         lastFM_songStartTime_.getTime()/1000);
5047                      if (resp_!=null && resp_.ok())
5048                      {
5049                        System.out.println("Song Sumbitted");
5050                      }
5051                      else
5052                      {
5053                        if (resp_ != null)
5054                        {
5055                          System.out.println("Sumbmit Failed --> (" +getLastfmErrorType(resp_.getStatus()) +") "+resp_.getMessage());
5056                          sc_ = handshakeWithLastfm(lastFM_userId);
5057                          System.out.println("Re-Submitting: "+ playList.getSongArtist(sel)+" "+
5058                                             playList.getSongTitle(sel)+" "+playList.getSongAlbum(sel)+
5059                                             " played for:"+playTime+
5060                                             "sec. at " + lastFM_songStartTime_.getTime()/1000);
5061                          resp_ = sc_.submit(playList.getSongArtist(sel),
5062                                             playList.getSongTitle(sel),
5063                                             playList.getSongAlbum(sel),
5064                                             playTime,
5065                                             playList.getTrackNumber(sel),
5066                                             Source.USER,
5067                                             lastFM_songStartTime_.getTime()/1000);
5068                          if (resp_!=null && resp_.ok())
5069                          {
5070                            System.out.println("Song Sumbitted");
5071                          }
5072                        }
5073                      }
5074                    }
5075                  }
5076        else
5077        {
5078          System.out.println("Song NOT submitted because it was too short or did not play long enough");
5079          log_.debug("Song NOT submitted because it was too short or did not play long enough");
5080        }
5081      }
5082      catch (IOException ioEx)
5083      {
5084        log_.minor("Last.fm submit failed --> (" +getLastfmErrorType(resp_.getStatus()) +") "+resp_.getMessage() ,ioEx);
5085      }
5086    }
5087    /* Last.fm Song Submit */
5088
5089    if (oggSyncState_!=null) oggSyncState_.clear();
5090    log_.debug("Done Song.");
5091    System.out.println("Done Song.");
5092    timerRunning_ = false;
5093    try
5094    {
5095      if (oggBitStream_ != null) oggBitStream_.close();
5096      playing_ = false; //playerThread_ = null;
5097    }
5098    catch (Exception e)
5099    {
5100    }
5101    button.setIcon(iconPlay_);
5102    miniButtonPlay.setIcon(iconMiniPlay_);
5103    if (miniViewShowing_)
5104    {
5105      buttonPause.setEnabled(false);
5106    }
5107    else
5108    {
5109      miniButtonPause.setEnabled(false);
5110    }
5111    log_.endMethod();
5112  }
5113
5114
5115  /**
5116   * Stops the current playing oggStream in the playerStream_.
5117   */
5118  public void stop()
5119  {
5120    final String methodName = className_ + ": stop()";
5121    log_.startMethod(methodName);
5122    if (!playing_)
5123    {
5124      try
5125      {
5126        outputLine.drain();
5127        outputLine.stop();
5128        outputLine.close();
5129        if (oggBitStream_ != null)
5130        {
5131          oggBitStream_.close();
5132        }
5133      }
5134      catch (Exception e)
5135      {
5136      }
5137    }
5138    playing_ = false; //playerThread_ = null;
5139    if (!running_as_applet)
5140    {
5141      if (miniViewShowing_)
5142      {
5143        xpos = popUpWin_.getX();
5144        ypos = popUpWin_.getY();
5145      }
5146      else
5147      {
5148        appXpos = appFrame_.getX();
5149        appYpos = appFrame_.getY();
5150      }
5151      storeConfigs();
5152      // last step is to save it as file
5153      //
5154      File file = new File(configFileName_);
5155      try
5156      {
5157        log_.debug("Storing config: "+configFileName_);
5158        cfgmgr_.store(file);
5159      }
5160      catch (Exception e)
5161      {
5162        // we have created it but cannot save it. That's bad
5163        // and let us see why....
5164        log_.minor("Did Not store config: "+configFileName_,e);
5165      }
5166    }
5167    log_.endMethod();
5168  }
5169
5170
5171  /**
5172   * Loads all the storable data from the config manager.
5173   **/
5174  private void loadConfigs()
5175  {
5176    final String methodName = className_ + ": loadConfigs()";
5177    log_.startMethod(methodName);
5178
5179    // get and set the general options
5180    // ==============================
5181    currVolSetting_ = Integer.parseInt(cfgmgr_.getProperty("lastVolume"));
5182    bufferMultiple_ = Integer.parseInt(cfgmgr_.getProperty("bufferMultiple"));
5183    volumeSlider_.setValue(currVolSetting_);
5184    currentVolumeMultiplier_ = volumeMultiplier(currVolSetting_);
5185    xpos = Integer.parseInt(cfgmgr_.getProperty("lastMiniXPostion"));
5186    ypos = Integer.parseInt(cfgmgr_.getProperty("lastMiniYPostion"));
5187    appXpos = Integer.parseInt(cfgmgr_.getProperty("lastNormalXPostion"));
5188    appYpos = Integer.parseInt(cfgmgr_.getProperty("lastNormalYPostion"));
5189    showMiniViewOnStart_ = (cfgmgr_.getProperty("lastViewSize").
5190      trim().equals("mini")?true:false);
5191    showPlaylistOnStart_ = (cfgmgr_.getProperty("lastPlaylistShowing").
5192      trim().equals("true")?true:false);
5193    autoPlayOnStart_ = (cfgmgr_.getProperty("autoPlayingOnStart").
5194      trim().equals("true")?true:false);
5195    lastFM_userId =  cfgmgr_.getProperty("lastFM_userId","","general");
5196    lastFM_userPass =  cfgmgr_.getProperty("lastFM_userPass","","general");
5197    lastFM_SessionKey =  cfgmgr_.getProperty("lastFM_SessionKey","","general");
5198    lastFM_token =  cfgmgr_.getProperty("lastFM_token","","general");
5199
5200    // get and set the logging level
5201    // ==============================
5202    String logLevel = cfgmgr_.getProperty("level","DEBUG","logging");
5203    short level = -1;
5204    if ("NONE".equals(logLevel)) level = Log.NONE;
5205    else if ("DEBUG".equals(logLevel)) level = Log.DEBUG;
5206    else if ("MINOR".equals(logLevel)) level = Log.MINOR;
5207    else if ("MAJOR".equals(logLevel)) level = Log.MAJOR;
5208    else if ("FULL".equals(logLevel)) level = Log.FULL;
5209    else if ("QUIET".equals(logLevel)) level = Log.QUIET;
5210    if (level != -1)
5211    {
5212      log_.debug("Setting Log Level to "+logLevel);
5213      log_.setLogLevel(level);
5214    }
5215
5216    // get and set the back colours
5217    // ============================
5218    boolean useLastBackColour = (cfgmgr_.
5219      getProperty("useLastBackColour","true","colours").
5220      trim().equals("true")?true:false);
5221    if(useLastBackColour)
5222    {
5223      log_.debug("setting Back Colours");
5224      String red = cfgmgr_.getProperty("lastBackColourRed","100","colours");
5225      String green = cfgmgr_.getProperty("lastBackColourGreen","180","colours");
5226      String blue = cfgmgr_.getProperty("lastBackColourBlue","245","colours");
5227      log_.debug("Back Colour="+red+" " +green+" " +blue);
5228      mainBackColour_ = new Color(
5229        Integer.parseInt(red),
5230        Integer.parseInt(green),
5231        Integer.parseInt(blue));
5232      setColours();
5233    }
5234
5235    // get and set the proxy detail
5236    // ============================
5237    areWeUsingProxy_ = (cfgmgr_.getProperty("proxy_useProxy","false","proxy").trim()
5238                                .toLowerCase().equals("true")?true:false);
5239    useProxyAuthentication_ = (cfgmgr_.getProperty("proxy_authenticate","proxy","proxy")
5240                                .trim().toLowerCase().equals("true")?true:false);
5241    proxyHost_ = cfgmgr_.getProperty("proxy_host","proxy","proxy");
5242    proxyPort_ = cfgmgr_.getProperty("proxy_port","80","proxy");
5243    proxyNoProxy_ = cfgmgr_.getProperty("proxy_noProxy","w3","proxy");
5244    proxyUsername_ = cfgmgr_.getProperty("proxy_userId","proxyUsername","proxy");
5245    proxyPassword_ = cfgmgr_.getProperty("proxy_userPass","proxyPassword","proxy");
5246
5247    System.out.println("Proxy Config="+areWeUsingProxy_+" " +proxyHost_+":" +proxyPort_+" " +proxyUsername_+"/" +proxyPassword_+" " +useProxyAuthentication_);
5248    //log_.debug("Proxy Config="+areWeUsingProxy_+" " +proxyHost_+":" +proxyPort_+" " +proxyUsername_+"/" +proxyPassword_+" " +useProxyAuthentication_);
5249    //Util.sleep(2000);
5250    log_.endMethod();
5251  }
5252
5253
5254  /**
5255   * Puts all the storable data in to the config manager in prep for saving.
5256   **/
5257  private void storeConfigs()
5258  {
5259    final String methodName = className_ + ": storeConfigs()";
5260    log_.startMethod(methodName);
5261
5262    if (!this.running_as_applet)
5263    {
5264      cfgmgr_.setProperty("lastNormalXPostion",
5265        String.valueOf(appFrame_.getX()));
5266      cfgmgr_.setProperty("lastNormalYPostion",
5267        String.valueOf(appFrame_.getY()));
5268      cfgmgr_.setProperty("lastMiniXPostion",
5269        String.valueOf(popUpWin_.getX()));
5270      cfgmgr_.setProperty("lastMiniYPostion",
5271        String.valueOf(popUpWin_.getY()));
5272    }
5273    cfgmgr_.setProperty("lastLooping",
5274      String.valueOf(checkBoxLoop.isSelected()));
5275    cfgmgr_.setProperty("lastRandom",
5276      String.valueOf(checkBoxRandom.isSelected()));
5277    cfgmgr_.setProperty("lastPlaylistShowing",
5278     String.valueOf(checkBoxPlaylist.isSelected()));
5279    cfgmgr_.setProperty("lastViewSize",(miniViewShowing_?"mini":"normal"));
5280    cfgmgr_.setProperty("lastVolume",String.valueOf(currVolSetting_));
5281    cfgmgr_.setProperty("useLastViewSize","true");
5282    cfgmgr_.setProperty("useLastPosition","true");
5283    cfgmgr_.setProperty("useLastVolume","true");
5284    cfgmgr_.setProperty("useLastLooping","true");
5285    cfgmgr_.setProperty("useLastRandom","true");
5286    cfgmgr_.setProperty("useLastPlaylistShowing",
5287                        (showPlaylistOnStart_?"true":"false"));
5288    cfgmgr_.setProperty("autoPlayingOnStart",
5289                        (autoPlayOnStart_?"true":"false"));
5290    cfgmgr_.setProperty("bufferMultiple",String.valueOf(bufferMultiple_));
5291    cfgmgr_.setProperty("lastFM_userId",lastFM_userId,"general");
5292    cfgmgr_.setProperty("lastFM_userPass",lastFM_userPass,"general");
5293    if(lastFM_Session!=null)cfgmgr_.setProperty("lastFM_SessionKey",lastFM_Session.getKey(),"general");
5294
5295    //
5296    // and now we add some properties to the category "proxy"
5297    //
5298    cfgmgr_.setProperty("proxy_useProxy",String.valueOf(areWeUsingProxy_),
5299                        "proxy");
5300    cfgmgr_.setProperty("proxy_authenticate",String.valueOf(useProxyAuthentication_),
5301                        "proxy");
5302    cfgmgr_.setProperty("proxy_host",proxyHost_,"proxy");
5303    cfgmgr_.setProperty("proxy_port",proxyPort_,"proxy");
5304    cfgmgr_.setProperty("proxy_noProxy",proxyNoProxy_,"proxy");
5305    cfgmgr_.setProperty("proxy_userId",proxyUsername_,"proxy");
5306    cfgmgr_.setProperty("proxy_userPass",proxyPassword_,"proxy");
5307
5308    //
5309    // and now we add some properties to the category "logging"
5310    //
5311    cfgmgr_.setProperty("enabled","true","logging");
5312    cfgmgr_.setProperty("file",logFile_,"logging");
5313    cfgmgr_.setProperty("level",log_.getLogLevelString(),"logging");
5314    cfgmgr_.setProperty("lastFont",displayFont_.getName(),"fonts");
5315    cfgmgr_.setProperty("lastFontAttributes","","fonts");
5316    cfgmgr_.setProperty("useLastFont","true","fonts");
5317    cfgmgr_.setProperty("lastBackColourRed",
5318      String.valueOf(mainBackColour_.getRed()),"colours");
5319    cfgmgr_.setProperty("lastBackColourGreen",
5320      String.valueOf(mainBackColour_.getGreen()),"colours");
5321    cfgmgr_.setProperty("lastBackColourBlue",
5322      String.valueOf(mainBackColour_.getBlue()),"colours");
5323    cfgmgr_.setProperty("useLastBackColour","true","colours");
5324
5325
5326    log_.endMethod();
5327  }
5328
5329
5330  /**
5331   * Creates all the storable data in to the config manager.
5332   **/
5333  private void createConfigs()
5334  {
5335    final String methodName = className_ + ": createConfigs()";
5336    log_.startMethod(methodName);
5337    // We are going to create a XML file now. There is now an empty
5338    // configuration available
5339    //
5340    // We create a second category. Note that there is already
5341    // the category "general" created
5342    //
5343    cfgmgr_.addCategory("general");
5344    cfgmgr_.addCategory("logging");
5345    cfgmgr_.addCategory("fonts");
5346    cfgmgr_.addCategory("colours");
5347    cfgmgr_.addCategory("quickButtons");
5348    cfgmgr_.addCategory("proxy");
5349    storeConfigs();
5350
5351      log_.endMethod();
5352}
5353
5354
5355  /**
5356   * Converts a linear mapped value to its Log equivalent. For use in the Volume
5357   * Scale.
5358   *
5359   * @param currSetting  is the linear value to convert. Acceptable values: 0 =
5360   *      mute, 10 = full, 11 is for fun.
5361   * @return             the Log value (Log currSetting)
5362   */
5363  public double volumeMultiplier(int currSetting)
5364  {
5365    final String methodName = className_ + ": volumeMultiplier()";
5366    log_.startMethod(methodName);
5367    double retVal = 0.0;
5368    double[] logLookup = {0.0000, 0.0400, 0.3010, 0.4771, 0.6021, 0.6990,
5369      0.7781, 0.8451, 0.9031, 0.9542, 1.0000, 1.1000};
5370    double[] inverseLogLookup = {0.0000, 1 - logLookup[9], 1 - logLookup[8],
5371      1 - logLookup[7], 1 - logLookup[6], 1 - logLookup[5],
5372      1 - logLookup[4],
5373      1 - logLookup[3], 1 - logLookup[2], 1 - logLookup[1],
5374      1.0000, 1.1000};
5375
5376    if (currSetting > 10)
5377    {
5378      retVal = 1.1;
5379    }
5380    else if (currSetting > 0)
5381    {
5382      if (logVolumeScale_)
5383      {
5384        retVal = inverseLogLookup[currSetting];
5385      }
5386      else
5387      {
5388        retVal = (double) currSetting / 10;
5389      }
5390    }
5391
5392    log_.endMethod();
5393
5394    return retVal;
5395  }
5396
5397
5398  /**
5399   * Handles all the Actions originating from the Control Buttons. *
5400   *
5401   * @param e  Description of Parameter
5402   */
5403  public void actionPerformed(ActionEvent e)
5404  {
5405    final String methodName = className_ + ": actionPerformed()";
5406    log_.startMethod(methodName);
5407    log_.startMethod("Action Source = " + e.getSource());
5408
5409    ImageIcon buttonIcon = (ImageIcon) ((JButton) (e.getSource())).getIcon();
5410    String command = "";
5411    if (buttonIcon != null)
5412    {
5413      command = buttonIcon.getDescription();
5414    }
5415    try
5416    {
5417      int currentItemIndex = playListComboBox.getSelectedIndex();
5418      log_.debug("\nCurrent Selected Index = "+currentItemIndex);
5419      int numSongs = playListComboBox.getItemCount();
5420      if (currentItemIndex < 0)
5421        currentItemIndex = 0;
5422      /* Play Button Was Pressed */
5423      /* *********************** */
5424      if (command.trim().equals("Play") && !playing_)
5425      {
5426        button.setIcon(iconStop_);
5427        buttonPause.setEnabled(true);
5428        button.setToolTipText("Stop Current Song");
5429        miniButtonPlay.setIcon(iconMiniStop_);
5430        miniButtonPause.setEnabled(true);
5431        miniButtonPlay.setToolTipText("Stop Current Song");
5432        log_.debug("\nPlay Button Pressed");
5433        System.out.println("Play Button");
5434        if (checkBoxLoop.isSelected())
5435        {
5436          log_.debug("\nLooping Songs");
5437          System.out.println("\nLooping "+numSongs+" Songs");
5438          //checkBoxLoop.setEnabled(false);
5439          looping_ = true;
5440          if (currentItemIndex > 0)
5441          {
5442            currentItemIndex--;
5443          }
5444          else
5445          {
5446            currentItemIndex = numSongs - 1;
5447          }
5448          playListComboBox.setSelectedIndex(currentItemIndex);
5449          String item = (String) (((JCheckBox) playListComboBox.
5450            getSelectedItem()).getText());
5451          log_.debug("\nPlay Button on item " +currentItemIndex + " " +item);
5452          playing_ = false; //playerThread_ = null;
5453          looperThread_ = new Thread(loopingRunnable_);
5454          looperThread_.start();
5455        }
5456        else
5457        {
5458          String item = (String) (((JCheckBox) playListComboBox.
5459            getSelectedItem()).getText());
5460          //        buttonLoop.setEnabled(true);
5461          tryPlay(playList.getURL(item));
5462        }
5463      }
5464      /* Stop Button Was Pressed */
5465      /* *********************** */
5466      else if (command.trim().equals("Stop"))// && playerThread_ != null)
5467      {
5468        System.out.println("Stop Button");
5469        loopPaused_ = false;
5470        playing_ = false;  // this stops this threads run method
5471        looping_ = false; // this stops the looping thread
5472        //checkBoxLoop.setEnabled(true);
5473        button.setToolTipText("Play Current Song In Playlist");
5474        button.setIcon(iconPlay_);
5475        buttonLast.setEnabled(true);
5476        buttonNext.setEnabled(true);
5477        buttonPause.setEnabled(false);
5478        miniButtonPlay.setToolTipText("Play Current Song In Playlist");
5479        miniButtonPlay.setIcon(iconMiniPlay_);
5480        miniButtonLast.setEnabled(true);
5481        miniButtonNext.setEnabled(true);
5482        miniButtonPause.setEnabled(false);
5483        Util.sleep(500);
5484        timeLabelValue.setText("00:00");
5485        miniTimeLabelValue.setText("00:00");
5486        appFrame_.setTitle(APP_NAME + " - No Songs Currently Playing");
5487      }
5488      /* Back Button Was Pressed */
5489      /* *********************** */
5490      else if (command.trim().equals("Back"))
5491      {
5492        System.out.println("Back Button");
5493        if (currentItemIndex > 0)
5494        {
5495          currentItemIndex--;
5496        }
5497        else
5498        {
5499          currentItemIndex = numSongs - 1;
5500        }
5501        if (looperThread_ != null && looperThread_.isAlive())
5502        {
5503          if (currentItemIndex > 0)
5504          {
5505            currentItemIndex--;
5506          }
5507          else
5508          {
5509            currentItemIndex = numSongs - 1;
5510          }
5511          playListComboBox.setSelectedIndex(currentItemIndex);
5512          playing_ = false; //playerThread_ = null;
5513          stop();
5514        }
5515        else
5516        {
5517          if (checkBoxRandom.isSelected())
5518          {
5519            currentItemIndex = (int) (Math.random() * playListComboBox.getItemCount());
5520          }
5521          playListComboBox.setSelectedIndex(currentItemIndex);
5522          playing_ = false; //playerThread_ = null;
5523          stop();
5524          String item = (String) (((JCheckBox) playListComboBox.getSelectedItem()).getText());
5525          tryPlay(playList.getURL(item));
5526        }
5527      }
5528      else if (command.trim().equals("Forward"))
5529      {
5530        if (looperThread_ != null)// && looperThread_.isAlive())
5531        {
5532          System.out.println("Next Song In Loop Button");
5533          playing_ = false; //playerThread_ = null;
5534          stop();
5535        }
5536        else
5537        {
5538          System.out.println("Start On Next Song Button");
5539          playing_ = false; //playerThread_ = null;
5540          stop();
5541          Util.sleep(1000);
5542          if (checkBoxRandom.isSelected())
5543          {
5544            System.out.println("...Random");
5545            currentItemIndex =
5546              (int) (Math.random() * playListComboBox.getItemCount());
5547          }
5548          else if (currentItemIndex < numSongs && currentItemIndex >= 0)
5549          {
5550            currentItemIndex++;
5551          }
5552          else
5553          {
5554            currentItemIndex = 0;
5555          }
5556          playListComboBox.setSelectedIndex(currentItemIndex);
5557          String item = (String) (((JCheckBox) playListComboBox.
5558            getSelectedItem()).getText());
5559          tryPlay(playList.getURL(item));
5560        }
5561      }
5562      else if (command.trim().equals("Pause"))
5563      {
5564        System.out.println("Pause Button");
5565        if (timerRunning_ && !loopPaused_)
5566        {
5567          loopPaused_ = true;
5568          buttonLast.setEnabled(false);
5569          buttonNext.setEnabled(false);
5570          miniButtonLast.setEnabled(false);
5571          miniButtonNext.setEnabled(false);
5572        }
5573        else
5574        {
5575          loopPaused_ = false;
5576          buttonPause.setBackground(buttonBackColour_);
5577          buttonLast.setEnabled(true);
5578          buttonNext.setEnabled(true);
5579          miniButtonPause.setBackground(buttonBackColour_);
5580          miniButtonLast.setEnabled(true);
5581          miniButtonNext.setEnabled(true);
5582        }
5583      }
5584      else if (command.trim().equals("Toggle Mini View"))
5585      {
5586        System.out.println("Toggle Mini View");
5587        if (miniViewShowing_)
5588        {
5589          showMiniView(false);
5590        }
5591        else
5592        {
5593          showMiniView(true);
5594        }
5595      }
5596      else if (command.trim().equals("Close jOggPlayer"))
5597      {
5598        System.out.println("Close App");
5599        playing_ = false;
5600        stop();
5601        log_.close();
5602        System.exit(0);
5603      }
5604      else
5605      {
5606        log_.debug("LeftOver ActionListner");
5607      }
5608    }
5609    catch (Exception ex)
5610    {
5611      log_.major("Action Listener Exception", ex);
5612    }
5613    log_.endMethod();
5614  }
5615}
5616
5617/*
5618 *  Here is the revision log
5619 *  ------------------------
5620 *  $Log: jOggPlayer.java,v $
5621 *  Revision 1.30  2004/11/14 19:31:43  tgutwin
5622 *  Bug Fix: The last Volume level is now used properly on statup.
5623 *
5624 *  Revision 1.28  2004/11/13 23:06:20  tgutwin
5625 *  Implemented the Authenticating Proxy.
5626 *  Started using the PlayList get methods to obtain the Vorbis comments instead of parsing them myself.
5627 *
5628 *  Revision 1.27  2003/05/01 05:42:36  tgutwin
5629 *  Added Javadoc comments dor describing Proxy usage requiring a username/Pass authentication.
5630 *  Also fixed the background/texture bug. (it couldn't find the image files).
5631 *
5632 *  Revision 1.26  2003/04/10 18:03:30  tgutwin
5633 *  Added code to delay the dismiss of the display Song Info tooltip so the user can have more time to read the song info.
5634 *
5635 *  Revision 1.25  2002/04/24 05:21:48  tgutwin
5636 *  Moved the Auto Start code into the main(). And Upped the version to 1.1.4.
5637 *
5638 *  Revision 1.24  2002/04/23 21:40:18  tgutwin
5639 *  Added the Auto Play on startup feature.
5640 *
5641 *  Revision 1.23  2002/04/11 23:13:25  anonymous
5642 *  Standardized the string needed for Util.loadImage. Also removed unneeded debug output to console. Added the capability to load a Playlist via the Load from URL dialog.
5643 *
5644 *  Revision 1.22  2002/04/06 06:27:32  anonymous
5645 *  Upped the version to 1.1.3
5646 *
5647 *  Revision 1.21  2002/04/06 06:13:58  anonymous
5648 *  changed the default loag level to MINOR in prep for 1.1.3 release
5649 *
5650 *  Revision 1.20  2002/04/05 23:08:44  anonymous
5651 *  Bug fixes when 1 or two items are in the list.
5652 *
5653 *  Revision 1.19  2002/04/04 23:05:56  anonymous
5654 *  Some Log Changes.
5655 *
5656 *  Revision 1.18  2002/01/28 06:33:13  tgutwin
5657 *
5658 *  Extra patch with the looping counters.
5659 *
5660 *  Revision 1.17  2002/01/27 23:01:57  tgutwin
5661 *
5662 *  Cleaned up the next checked item bug that was screwing up the
5663 *  looping and playing of checked items.
5664 *  Upped the version Num to 1.1.2
5665 *
5666 *  Revision 1.16  2002/01/02 05:52:52  root
5667 *
5668 *  Version 1.1.0 release.
5669 *
5670 *  Revision 1.15  2001/12/17 07:34:45  tgutwin
5671 *
5672 *  Bug Fix bufferMultiple config item.
5673 *
5674 *  Revision 1.14  2001/12/17 06:59:37  tgutwin
5675 *
5676 *  Added a user settable Buffer size dialog.
5677 *
5678 *  Revision 1.13  2001/12/16 07:23:55  tgutwin
5679 *
5680 *  Added Items to the help text.
5681 *  Loads the last colours from the config xml doc.
5682 *  Added a Mute Button.
5683 *  Favourite spelling.
5684 *  Added an option menu item and moved items into it.
5685 *  Playlist area now follows any background colour changes.
5686 *  Added the menu to the display area.
5687 *  Playlist file chooser now can have either a save/open dialog.
5688 *
5689 *  Revision 1.12  2001/12/02 07:40:40  tgutwin
5690 *
5691 *  Fixed the VERSION String to be 1.1 pre 4. For release.
5692 *
5693 *  Revision 1.11  2001/12/02 07:32:34  tgutwin
5694 *
5695 *  One last applet check.
5696 *
5697 *  Revision 1.9  2001/11/21 03:54:10  tgutwin
5698 *
5699 *  Added a draggable title button to the mini view.
5700 *
5701 *  Revision 1.8  2001/11/17 03:49:10  tgutwin
5702 *  Added a little area to drag the miniview.
5703 *  Revision 1.7  2001/11/17 01:56:17  tgutwin
5704 *  Upped the version and added a draggable area holder for the mini-view.
5705 *  Revision 1.6  2001/11/16 05:51:47  tgutwin
5706 *  Mini View 90% complete.
5707 *  Revision 1.5  2001/08/12 06:04:18  tgutwin
5708 *  Moved PlayList into ca.bc.webarts.widgets.
5709 *  Added a bunch of JavaDocs.
5710 *  Renamed Many vars to be more descriptive.
5711 *  General Code Cleanup.
5712 *  NO NEW FEATURES.
5713 *  Revision 1.4  2001/08/03 00:00:09  tgutwin
5714 *  Improved the Layout Managers
5715 *  Revision 1.3  2001/06/16 21:40:03  tgutwin
5716 *  Added CVS Keywords and headers
5717 *  Revision 1.2  2001/06/16 21:35:11  tgutwin
5718 *  Added CVS Keywords and headers
5719 */