diff --git a/projects/robodj/src/java/robodj/chooser/Chooser.java b/projects/robodj/src/java/robodj/chooser/Chooser.java new file mode 100644 index 00000000..2e72cec2 --- /dev/null +++ b/projects/robodj/src/java/robodj/chooser/Chooser.java @@ -0,0 +1,71 @@ +// +// $Id: Chooser.java,v 1.1 2001/06/05 16:42:38 mdb Exp $ + +package robodj.chooser; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.io.IOException; +import java.sql.SQLException; +import java.util.Properties; + +import com.samskivert.util.PropertiesUtil; + +import robodj.Log; +import robodj.repository.Repository; +import robodj.util.ServerControl; + +/** + * The chooser is the GUI-based application for browsing the music + * collection and managing the playlist. + */ +public class Chooser +{ + public static Properties config; + + public static Repository repository; + + public static ServerControl scontrol; + + public static void main (String[] args) + { + // set up our configuration by hand for now + config = new Properties(); + config.setProperty("repository.db.driver", "org.gjt.mm.mysql.Driver"); + config.setProperty("repository.db.username", "www"); + config.setProperty("repository.db.password", "Il0ve2PL@Y"); + config.setProperty("repository.db.url", + "jdbc:mysql://depravity:3306/robodj"); + config.setProperty("repository.basedir", "/export/robodj/repository"); + + // create an interface to the database repository + try { + Properties dbprops = + PropertiesUtil.getSubProperties(config, "repository.db"); + repository = new Repository(dbprops); + } catch (SQLException sqe) { + Log.warning("Unable to establish communication with music " + + "database: " + sqe); + System.exit(-1); + } + + try { + // establish a connection with the music server + scontrol = new ServerControl("depravity", 2500); + } catch (IOException ioe) { + Log.warning("Unable to establish communication with music " + + "server: " + ioe); + System.exit(-1); + } + + // create our primary user interface frame, center the frame in + // the screen and show it + ChooserFrame frame = new ChooserFrame(); + Toolkit tk = frame.getToolkit(); + Dimension ss = tk.getScreenSize(); + int width = 550, height = 500; + frame.setBounds((ss.width-width)/2, (ss.height-height)/2, + width, height); + frame.setVisible(true); + } +} diff --git a/projects/robodj/src/java/robodj/chooser/ChooserFrame.java b/projects/robodj/src/java/robodj/chooser/ChooserFrame.java new file mode 100644 index 00000000..c53b3d68 --- /dev/null +++ b/projects/robodj/src/java/robodj/chooser/ChooserFrame.java @@ -0,0 +1,101 @@ +// +// $Id: ChooserFrame.java,v 1.1 2001/06/05 16:42:38 mdb Exp $ + +package robodj.chooser; + +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.*; + +import com.samskivert.swing.*; + +public class ChooserFrame + extends JFrame + implements ActionListener +{ + public ChooserFrame () + { + super("RoboDJ Chooser"); + + // we create a top-level panel to manage everything + JPanel top = new JPanel(); + GroupLayout gl = new VGroupLayout(GroupLayout.STRETCH); + gl.setOffAxisPolicy(GroupLayout.STRETCH); + top.setLayout(gl); + + // give ourselves a wee bit of a border + top.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + + // the top of the UI is the playlist manager section + JTabbedPane tpane = new JTabbedPane(); + Component elist = new EntryList(); + tpane.addTab("Browse", null, elist, "Browse music database."); + tpane.setSelectedIndex(0); + top.add(tpane); + + // the bottom is the control bar + GroupLayout bgl = new HGroupLayout(GroupLayout.NONE); + bgl.setJustification(GroupLayout.RIGHT); + JPanel cbar = new JPanel(bgl); + + // add some fake control buttons for now + cbar.add(createControlButton("Play", "play")); + cbar.add(createControlButton("Pause", "pause")); + cbar.add(createControlButton("Stop", "stop")); + cbar.add(createControlButton("Skip", "skip")); + cbar.add(createControlButton("Clear", "clear")); + cbar.add(createControlButton("Exit", "exit")); + + // stick it into the frame + top.add(cbar, GroupLayout.FIXED); + + // now add our top-level panel (we'd not use this if we could set + // a border on the content pane returned by the frame... alas) + getContentPane().add(top, BorderLayout.CENTER); + } + + protected JButton createControlButton (String label, String action) + { + JButton cbut = new JButton(label); + cbut.setActionCommand(action); + cbut.addActionListener(this); + return cbut; + } + + public void actionPerformed (ActionEvent e) + { + String cmd = e.getActionCommand(); + if (cmd.equals("exit")) { + System.exit(0); + + } else if (cmd.equals("pause")) { + Chooser.scontrol.pause(); + + } else if (cmd.equals("play")) { + Chooser.scontrol.play(); + + } else if (cmd.equals("clear")) { + Chooser.scontrol.clear(); + + } else if (cmd.equals("stop")) { + Chooser.scontrol.stop(); + + } else if (cmd.equals("skip")) { + Chooser.scontrol.skip(); + + } else { + System.out.println("Unknown action event: " + cmd); + } + } + + protected Component makeTextPanel (String text) + { + JPanel panel = new JPanel(false); + JLabel filler = new JLabel(text); + filler.setHorizontalAlignment(JLabel.CENTER); + panel.setLayout(new GridLayout(1, 1)); + panel.add(filler); + return panel; + } +} diff --git a/projects/robodj/src/java/robodj/chooser/EntryList.java b/projects/robodj/src/java/robodj/chooser/EntryList.java new file mode 100644 index 00000000..4c30175f --- /dev/null +++ b/projects/robodj/src/java/robodj/chooser/EntryList.java @@ -0,0 +1,233 @@ +// +// $Id: EntryList.java,v 1.1 2001/06/05 16:42:38 mdb Exp $ + +package robodj.chooser; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.sql.SQLException; +import java.util.*; +import javax.swing.*; + +import com.samskivert.swing.*; +import com.samskivert.swing.util.*; + +import robodj.Log; +import robodj.repository.*; + +public class EntryList + extends JPanel + implements TaskObserver, ActionListener +{ + public EntryList () + { + GroupLayout gl = new VGroupLayout(GroupLayout.STRETCH); + gl.setOffAxisPolicy(GroupLayout.STRETCH); + setLayout(gl); + + // create the pane that will hold the buttons + gl = new VGroupLayout(GroupLayout.NONE); + gl.setOffAxisPolicy(GroupLayout.EQUALIZE); + _bpanel = new JPanel(gl); + + // give ourselves a wee bit of a border + _bpanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + + // put it into a scrolling pane + JScrollPane bscroll = new JScrollPane(_bpanel); + add(bscroll); + + // add our navigation button + _upbut = new JButton("Up"); + _upbut.setActionCommand("up"); + _upbut.addActionListener(this); + add(_upbut, GroupLayout.FIXED); + + // start up the task that reads the CD info from the database + TaskMaster.invokeMethodTask("readEntries", this, this); + } + + public void taskCompleted (String name, Object result) + { + if (name.equals("readEntries")) { + // the result should be an array of entry objects with which + // we can populate our button list + _entries = (Entry[])result; + populateEntries(_entries); + + } else if (name.equals("readAndPlay")) { + for (int i = 0; i < _entry.songs.length; i++) { + Chooser.scontrol.append(_entry.songs[i].location); + } + + } else if (name.equals("readSongs")) { + populateSong(_entry); + } + } + + public void taskFailed (String name, Throwable exception) + { + String msg; + if (Exception.class.equals(exception.getClass())) { + msg = exception.getMessage(); + } else { + msg = exception.toString(); + } + JOptionPane.showMessageDialog(this, msg, "Error", + JOptionPane.ERROR_MESSAGE); + Log.logStackTrace(exception); + } + + /** + * Reads the entries from the database. + */ + public Entry[] readEntries () + throws SQLException + { + return Chooser.repository.getEntries(""); + } + + /** + * Reads the entries from the database. + */ + public void readSongs () + throws SQLException + { + Chooser.repository.populateSongs(_entry); + } + + /** + * Reads the entries from the database and plays them all. + */ + public void readAndPlay () + throws SQLException + { + Chooser.repository.populateSongs(_entry); + } + + /** + * Creates the proper buttons, etc. for each entry. + */ + protected void populateEntries (Entry[] entries) + { + // disable the up button because we're at the top level + _upbut.setEnabled(false); + + // clear out any existing children + _bpanel.removeAll(); + + // sort our entries + Comparator ecomp = new Comparator() { + public int compare (Object o1, Object o2) { + Entry e1 = (Entry)o1, e2 = (Entry)o2; + int rv = e1.artist.compareTo(e2.artist); + return rv == 0 ? e1.title.compareTo(e2.title) : rv; + } + public boolean equals (Object o1) { + return o1.equals(this); + } + }; + Arrays.sort(entries, ecomp); + + // and add buttons for every entry + String artist = null; + for (int i = 0; i < entries.length; i++) { + if (!entries[i].artist.equals(artist)) { + artist = entries[i].artist; + JLabel label = new JLabel(entries[i].artist); + _bpanel.add(label); + } + + // create a browse and a play button + JPanel hpanel = new JPanel(); + GroupLayout gl = new HGroupLayout(GroupLayout.NONE); + gl.setOffAxisPolicy(GroupLayout.STRETCH); + gl.setJustification(GroupLayout.LEFT); + hpanel.setLayout(gl); + + JButton button; + + button = new JButton("Play"); + button.setActionCommand("playall"); + button.addActionListener(this); + button.putClientProperty("entry", entries[i]); + hpanel.add(button); + + button = new JButton(entries[i].title); + button.setActionCommand("browse"); + button.addActionListener(this); + button.putClientProperty("entry", entries[i]); + hpanel.add(button); + + _bpanel.add(hpanel); + } + } + + protected void populateSong (Entry entry) + { + // enable the up button because we're looking at a song + _upbut.setEnabled(true); + + // clear out any existing children + _bpanel.removeAll(); + + // add a label for the title + JLabel label = new JLabel(entry.title); + _bpanel.add(label); + + // sort the songs by position + Comparator scomp = new Comparator() { + public int compare (Object o1, Object o2) { + Song s1 = (Song)o1, s2 = (Song)o2; + return s1.position - s2.position; + } + public boolean equals (Object o1) { + return o1.equals(this); + } + }; + Arrays.sort(entry.songs, scomp); + + // and add buttons for every song + for (int i = 0; i < entry.songs.length; i++) { + JButton button = new JButton(entry.songs[i].title); + button.setActionCommand("play"); + button.addActionListener(this); + button.putClientProperty("song", entry.songs[i]); + _bpanel.add(button); + } + } + + public void actionPerformed (ActionEvent e) + { + String cmd = e.getActionCommand(); + if (cmd.equals("browse")) { + JButton src = (JButton)e.getSource(); + _entry = (Entry)src.getClientProperty("entry"); + // start up the task that reads this CDs songs from the database + TaskMaster.invokeMethodTask("readSongs", this, this); + + } else if (cmd.equals("playall")) { + JButton src = (JButton)e.getSource(); + _entry = (Entry)src.getClientProperty("entry"); + // start up the task that reads this CDs songs from the database + TaskMaster.invokeMethodTask("readAndPlay", this, this); + + } else if (cmd.equals("play")) { + JButton src = (JButton)e.getSource(); + Song song = (Song)src.getClientProperty("song"); + Chooser.scontrol.append(song.location); + + } else if (cmd.equals("up")) { + populateEntries(_entries); + + } else { + System.out.println("Unknown action event: " + cmd); + } + } + + protected JPanel _bpanel; + protected JButton _upbut; + + protected Entry[] _entries; + protected Entry _entry; +}