/* * Jajuk * Copyright (C) The Jajuk Team * http://jajuk.info * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ package org.jajuk.ui.wizard; import entagged.freedb.Freedb; import entagged.freedb.FreedbAlbum; import entagged.freedb.FreedbException; import entagged.freedb.FreedbQueryResult; import entagged.freedb.FreedbReadResult; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; import java.util.Locale; import javax.swing.DefaultComboBoxModel; import javax.swing.JLabel; import javax.swing.JScrollPane; import javax.swing.SwingWorker; import net.miginfocom.swing.MigLayout; import org.jajuk.base.FileManager; import org.jajuk.base.Track; import org.jajuk.base.TrackManager; import org.jajuk.events.JajukEvent; import org.jajuk.events.JajukEvents; import org.jajuk.events.ObservationManager; import org.jajuk.services.cddb.CDDBTrack; import org.jajuk.ui.helpers.CDDBTableModel; import org.jajuk.ui.widgets.InformationJPanel; import org.jajuk.ui.widgets.JajukJDialog; import org.jajuk.ui.widgets.JajukTable; import org.jajuk.ui.widgets.OKCancelPanel; import org.jajuk.ui.widgets.SteppedComboBox; import org.jajuk.ui.windows.JajukMainWindow; import org.jajuk.util.Messages; import org.jajuk.util.UtilGUI; import org.jajuk.util.UtilString; import org.jajuk.util.error.JajukException; import org.jajuk.util.log.Log; /** * . */ public class CDDBWizard extends JajukJDialog implements ActionListener { /** Generated serialVersionUID. */ private static final long serialVersionUID = 1L; private SteppedComboBox jcbAlbum; private JajukTable jtable; private CDDBTableModel model; /** OK/Cancel panel. */ private OKCancelPanel okc; /** Items to be retagged. */ private List<CDDBTrack> alCddbTracks; /** Freedb Items. */ private Freedb fdb; private FreedbQueryResult[] foundAlbums; private FreedbReadResult fdbReader; private List<String> jcbFoundAlbums; /** * CDDB wizard. * * @param tracks */ public CDDBWizard(final List<Track> tracks) { super(JajukMainWindow.getInstance(), false); UtilGUI.waiting(); // windows title: absolute path name of the given directory setTitle(Messages.getString("CDDBWizard.19")); setModal(true); SwingWorker<Void, Void> sw = new SwingWorker<Void, Void>() { @Override public Void doInBackground() { try { // Put an error message if no tracks were found if (tracks.size() == 0) { return null; } else { // Convert given tracks into CDDBTracks alCddbTracks = new ArrayList<CDDBTrack>(tracks.size()); for (Track t : tracks) { CDDBTrack track = new CDDBTrack(t); if (!alCddbTracks.contains(track)) { alCddbTracks.add(track); } } // Perform CDDB Query and display an error message if CDDB query // don't found any match CDDBTrack[] cddbtracks = alCddbTracks.toArray(new CDDBTrack[alCddbTracks.size()]); int results = performQuery(cddbtracks); if (results == 0) { Messages.showInfoMessage(Messages.getString("CDDBWizard.12")); return null; } } } catch (Exception e) { Log.error(e); } finally { UtilGUI.stopWaiting(); } return null; } @Override public void done() { if (foundAlbums != null && foundAlbums.length > 0) { jtable = populateTable(); initUI(); } } }; sw.execute(); } /** * Fill the table. * * @return the jajuk table */ public JajukTable populateTable() { model = populateModel(); jtable = new JajukTable(model, true, null); jtable.selectAll(); jtable.packAll(); return jtable; } /** * Populate model. * * @return the cDDB table model */ public CDDBTableModel populateModel() { try { // Display first result found when the frame opens, then select the combo // index int index = 0; if (jcbAlbum != null) { index = jcbAlbum.getSelectedIndex(); } fdbReader = fdb.read(foundAlbums[index]); // Can sometimes be null for some reasons if (fdbReader == null) { throw new FreedbException("Void Freereader, please retry"); } } catch (FreedbException e) { Messages.showDetailedErrorMessage(174, e.getLocalizedMessage(), null); Log.debug("CDDB error ! " + e.getLocalizedMessage()); dispose(); } // Re-populate model model = new CDDBTableModel(); model.populateModel(alCddbTracks, fdbReader); // Force table refreshing model.fireTableDataChanged(); return model; } /** * Inits the ui. */ public void initUI() { okc = new OKCancelPanel(CDDBWizard.this, Messages.getString("Apply"), Messages.getString("Close")); // Albums List jcbAlbum = new SteppedComboBox(); // add all matches jcbAlbum.setModel(new DefaultComboBoxModel(jcbFoundAlbums.toArray())); jcbAlbum.setSelectedIndex(jcbAlbum.getSelectedIndex()); jcbAlbum.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent arg0) { // Update table model = populateModel(); jtable.setModel(model); jtable.selectAll(); } }); // Show the number of matches found JLabel jlCurrent = new JLabel(foundAlbums.length + " " + Messages.getString("CDDBWizard.18")); // Add items setLayout(new MigLayout("insets 10,gapx 15,gapy 15", "[grow,800:800:]")); add(new JLabel(Messages.getString("CDDBWizard.5")), "split 3"); add(jcbAlbum, "grow"); add(jlCurrent, "wrap"); add(new JScrollPane(jtable), "grow,wrap"); add(okc, "span,right"); getRootPane().setDefaultButton(okc.getOKButton()); pack(); setLocationRelativeTo(JajukMainWindow.getInstance()); setVisible(true); } /** * Perform the actual freedb query. * * @param cddbtracks * * @return number of results (0 if no result). -1 if a technical problem * occurred. */ public int performQuery(CDDBTrack[] cddbtracks) { fdb = new Freedb(); FreedbAlbum fdbAlbum = new FreedbAlbum(cddbtracks); try { foundAlbums = fdb.query(fdbAlbum); jcbFoundAlbums = new ArrayList<String>(foundAlbums.length); for (FreedbQueryResult foundAlbum : foundAlbums) { jcbFoundAlbums.add("[" + foundAlbum.getDiscId() + "] " + UtilString.getLimitedString((foundAlbum.getArtist() + " / " + foundAlbum.getAlbum()), 40)); if (foundAlbum.isExactMatch()) { InformationJPanel.getInstance().setMessage(Messages.getString("CDDBWizard.17"), InformationJPanel.MessageType.INFORMATIVE); } } return foundAlbums.length; } catch (FreedbException e) { Log.debug(e.getLocalizedMessage()); // freedb throws a Freedb exception for network problem or no match found // we want to display an error message only in the first case if (e.getMessage().toLowerCase(Locale.getDefault()).indexOf("no match") == -1) { Messages.showErrorMessage(174, e.getLocalizedMessage()); return -1; } return 0; } catch (Exception e) { Log.debug(e.getLocalizedMessage()); Messages.showErrorMessage(174, e.getLocalizedMessage()); return -1; } } /** * Retag files. */ public void retagFiles() { int[] aIdxToTag = jtable.getSelectedRows(); if (aIdxToTag.length == 0) { dispose(); } else { for (int iRow : aIdxToTag) { // Unset autocommit to tags so we write to file only once for all // changed tags for a single file TrackManager.getInstance().setAutocommit(false); Track track = alCddbTracks.get(iRow).getTrack(); try { track = retagInternal(iRow, track); // Commit all tags for a single file (we prefer this to make sure some // tracks will be changed, so we don't commit all tags for all files) TrackManager.getInstance().commit(); } catch (JajukException e) { Log.error(e); Messages.showErrorMessage(155, track.getName()); dispose(); // Stop retagging if one track cannot be written to avoid displaying // several error messages // TODO a better handling could be to finish all tag writes and // displaying a grouped list of failed items like in properties panel break; } finally { TrackManager.getInstance().setAutocommit(true); } } InformationJPanel.getInstance().setMessage(Messages.getString("Success"), InformationJPanel.MessageType.INFORMATIVE); // Force files resorting to ensure the sorting consistency, indeed, // files are sorted by name *and* track order and we need to force a files // resort after an order change (this is already done in case of file name // change) FileManager.getInstance().forceSorting(); ObservationManager.notify(new JajukEvent(JajukEvents.DEVICE_REFRESH)); } } /** * Retag internal. * * @param iRow * @param trackin * * @return the track * * @throws JajukException the jajuk exception */ private Track retagInternal(final int iRow, final Track trackin) throws JajukException { Track track = trackin; String sValue = fdbReader.getAlbum(); if (sValue != null && sValue.trim().length() > 0) { track = TrackManager.getInstance().changeTrackAlbum(track, sValue, null); } sValue = fdbReader.getArtist(); if (sValue != null && sValue.trim().length() > 0) { track = TrackManager.getInstance().changeTrackArtist(track, sValue, null); } sValue = fdbReader.getTrackTitle(iRow); if (sValue != null && sValue.trim().length() > 0) { track = TrackManager.getInstance().changeTrackName(track, sValue, null); } sValue = fdbReader.getGenre(); if (sValue != null && sValue.trim().length() > 0) { track = TrackManager.getInstance().changeTrackGenre(track, sValue, null); } // Track# can be absent from CDDB database, ignore if not provided try { long lValue = fdbReader.getTrackNumber(iRow); if (lValue > 0) { track = TrackManager.getInstance().changeTrackOrder(track, lValue, null); } } catch (NumberFormatException e) { Log.debug(e); } // Same for year try { long lValue = Long.parseLong(fdbReader.getYear()); if (lValue > 0 && lValue < 3000) { // Review this after year 3000 // Fry ;-) track = TrackManager.getInstance().changeTrackYear(track, fdbReader.getYear(), null); } } catch (NumberFormatException e) { Log.debug(e); } return track; } /* * (non-Javadoc) * * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == okc.getCancelButton()) { dispose(); } if (e.getSource() == okc.getOKButton()) { dispose(); new Thread("CDDBWizard Action Thread") { @Override public void run() { retagFiles(); } }.start(); } } }