MPDPlaylist.java :  » Client » pmix » org » a0z » mpd » Android Open Source

Android Open Source » Client » pmix 
pmix » org » a0z » mpd » MPDPlaylist.java
package org.a0z.mpd;

import java.io.IOException;
import java.net.URL;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.a0z.mpd.url.UnsupportedMimeTypeException;

/**
 * MPD Playlist controller.
 * @author Felipe Gustavo de Almeida, Stefan Agner
 * @version $Id: MPDPlaylist.java 2716 2004-11-20 17:37:20Z galmeida $
 */
public class MPDPlaylist {
    private static final String MPD_CMD_PLAYLIST_ADD = "add";

    private static final String MPD_CMD_PLAYLIST_CLEAR = "clear";

    private static final String MPD_CMD_PLAYLIST_DELETE = "rm";

    private static final String MPD_CMD_PLAYLIST_LIST = "playlistid";

    private static final String MPD_CMD_PLAYLIST_CHANGES = "plchanges";

    private static final String MPD_CMD_PLAYLIST_LOAD = "load";

    private static final String MPD_CMD_PLAYLIST_MOVE = "move";

    private static final String MPD_CMD_PLAYLIST_MOVE_ID = "moveid";

    private static final String MPD_CMD_PLAYLIST_REMOVE = "delete";

    private static final String MPD_CMD_PLAYLIST_REMOVE_ID = "deleteid";

    private static final String MPD_CMD_PLAYLIST_SAVE = "save";

    private static final String MPD_CMD_PLAYLIST_SHUFFLE = "shuffle";

    private static final String MPD_CMD_PLAYLIST_SWAP = "swap";

    private static final String MPD_CMD_PLAYLIST_SWAP_ID = "swapid";

    private MusicList list;

    private int lastPlaylistVersion = -1;

    private boolean firstRefresh = true;

    private MPD mpd;

    /**
     * Creates a new playlist.
     */
    MPDPlaylist(MPD mpd) {
        this.list = new MusicList();
        this.mpd = mpd;
    }

    /**
     * Adds a <code>Collection</code> of <code>Music</code> to playlist.
     * @param c <code>Collection</code> of <code>Music</code> to be added to playlist.
     * @throws MPDServerException if an error occur while contacting server.
     * @see Music
     */
    public void add(Collection c) throws MPDServerException {
        Iterator it = c.iterator();

        while (it.hasNext()) {
            Music music = (Music) it.next();
            String[] args = new String[1];
            args[0] = music.getFullpath();
            this.mpd.getMpdConnection().queueCommand(MPD_CMD_PLAYLIST_ADD, args);
        }
        this.mpd.getMpdConnection().sendCommandQueue();
        this.refresh();
    }

    /**
     * Adds a music to playlist.
     * @param music music to be added.
     * @throws MPDServerException if an error occur while contacting server.
     */
    public void add(Music music) throws MPDServerException {
        String[] args = new String[1];
        args[0] = music.getFullpath();
        this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_ADD, args);
        this.refresh();
    }
    
    /**
     * Adds a music to playlist recursivly.
     * @param music music to be added.
     * @throws MPDServerException if an error occur while contacting server.
     */
    public void add(Directory music) throws MPDServerException {
        String[] args = new String[1];
        args[0] = music.getFullpath();
        this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_ADD, args);
        this.refresh();
    }

    /**
     * Adds a stream to playlist.
     * @param url streams's url
     * @throws MPDServerException on server error.
     * @throws MPDClientException on client error.
     */
    public void add(URL url) throws MPDServerException, MPDClientException {
        List urlContent;
        try {
            urlContent = (List) url.openConnection().getContent();
        } catch (UnsupportedMimeTypeException e) {
            //if mimetype is not supported by JMPDComm try to pass it directly to MPD.
            urlContent = new LinkedList();
            urlContent.add(url.toString());
        } catch (IOException e) {
            throw new MPDClientException("Unable to fetch " + url.toString(), e);
        }
        if (urlContent.size() > 0) {
            String[] args = new String[1];
            Iterator it = urlContent.iterator();
            while (it.hasNext()) {
                args[0] = (String) it.next();
                this.mpd.getMpdConnection().queueCommand(MPD_CMD_PLAYLIST_ADD, args);
            }
            this.mpd.getMpdConnection().sendCommandQueue();
            this.refresh();
        }
    }

    /**
     * Clears playlist content.
     * @throws MPDServerException if an error occur while contacting server.
     */
    public void clear() throws MPDServerException {
        this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_CLEAR);
        list.clear();
    }

    /**
     * Retrieves music at position idx in playlist. Operates on local copy of playlist, may not reflect server's current
     * playlist. You may call refresh() before calling get().
     * @param idx position.
     * @return music at position idx.
     */
    public Music getMusic(int idx) {
        return (Music) list.getByIndex(idx);
    }

    /**
     * Load playlist file.
     * @param file playlist filename without .m3u extension.
     * @throws MPDServerException if an error occur while contacting server.
     */
    public void load(String file) throws MPDServerException {
        String[] args = new String[1];
        args[0] = file;
        this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_LOAD, args);
    }

    /**
     * Moves song at position <code>from</code> to position <code>to</code>.
     * @param from current position of the song to be moved.
     * @param to target position of the song to be moved.
     * @throws MPDServerException if an error occur while contacting server.
     * @deprecated use <code>move</code>
     * @see #move(int, int)
     */
    public void moveByPosition(int from, int to) throws MPDServerException {
        String[] args = new String[2];
        args[0] = Integer.toString(from);
        args[0] = Integer.toString(to);
        this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_MOVE, args);
        this.refresh();
    }

    /**
     * Moves song with specified id to position <code>to</code>.
     * @param songId Id of the song to be moved.
     * @param to target position of the song to be moved.
     * @throws MPDServerException if an error occur while contacting server.
     */
    public void move(int songId, int to) throws MPDServerException {
        String[] args = new String[2];
        args[0] = Integer.toString(songId);
        args[0] = Integer.toString(to);
        this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_MOVE_ID, args);
        this.refresh();
    }

    /**
     * Reload playlist content. <code>refresh</code> has better performance and is more server friendly, use it
     * whenever possible.
     * @see #refresh(int)
     * @throws MPDServerException if an error occur while contacting server.
     * @return current playlist version.
     */
    public int refresh() throws MPDServerException {
        if (firstRefresh) {
            this.lastPlaylistVersion = this.reload();
            firstRefresh = false;
        } else {
            this.lastPlaylistVersion = this.refresh(lastPlaylistVersion);
        }
        return this.lastPlaylistVersion;
    }

    /**
     * Reload playlist content. <code>refresh</code> has better performance and is more server friendly, use it
     * whenever possible.
     * @see #refresh(int)
     * @throws MPDServerException if an error occur while contacting server.
     * @return current playlist version.
     */
    private int reload() throws MPDServerException {
      LinkedList<Music> playlist = new LinkedList<Music>();
      LinkedList<String> file = new LinkedList<String>();
        //TODO should be atomic
        MPDStatus status = this.mpd.getStatus();
        List<String> response = this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_LIST);
        int index = 0;
        for (String line : response) {
            if (line.startsWith("file: ")) {
                if (file.size() != 0) {
                    playlist.add(new Music(file));
                    index++;
                    file.clear();
                }
            }
            file.add(line);
        }

        if (file.size() != 0) {
            playlist.add(new Music(file));
        }

        this.list.clear();
        this.list.addAll(playlist);
        return status.getPlaylistVersion();
    }

    /**
     * Do incremental update of playlist contents.
     * @param playlistVersion last read playlist version
     * @throws MPDServerException if an error occur while contacting server.
     * @return current playlist version.
     */
    public int refresh(int playlistVersion) throws MPDServerException {
        MusicList playlist = new MusicList(list);
        List file = new LinkedList();
        String[] args = new String[1];
        args[0] = Integer.toString(playlistVersion);
        // TODO should be atomic
        MPDStatus status = this.mpd.getStatus();
        List response = this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_CHANGES, args);
        Iterator it = response.iterator();
        while (it.hasNext()) {
            String line = (String) it.next();

            if (line.startsWith("file: ")) {
                if (file.size() != 0) {
                    playlist.add(new Music(file));
                    file.clear();
                }
            }
            file.add(line);
        }

        if (file.size() != 0) {
            playlist.add(new Music(file));
        }

        this.list.clear();
        this.list.addAll(playlist.subList(0, status.getPlaylistLength()));
        return status.getPlaylistVersion();
    }

    /**
     * Removes playlist file.
     * @param file playlist filename without .m3u extension.
     * @throws MPDServerException if an error occur while contacting server.
     */
    public void removePlaylist(String file) throws MPDServerException {
        String[] args = new String[1];
        args[0] = file;
        this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_DELETE, args);
    }

    /**
     * Remove playlist entry at position idx.
     * @param position position of the entry to be removed.
     * @throws MPDServerException if an error occur while contacting server.
     * @deprecated use <code>removeSong</code>.
     * @see #removeSong(int)
     */
    public void removeSongByPosition(int position) throws MPDServerException {
        String[] args = new String[1];
        args[0] = Integer.toString(position);
        this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_REMOVE, args);
        list.removeByPosition(position);
    }

    /**
     * Remove playlist entry at position idx.
     * @param songId id of the entry to be removed.
     * @throws MPDServerException if an error occur while contacting server.
     */
    public void removeSong(int songId) throws MPDServerException {
        String[] args = new String[1];
        args[0] = Integer.toString(songId);
        this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_REMOVE_ID, args);
        list.removeBySongId(songId);
    }

    /**
     * Removes entries from playlist.
     * @param songs entries positions.
     * @throws MPDServerException if an error occur while contacting server.
     * @deprecated use <code>removeSongs</code>
     * @see #removeSongs(int[])
     */
    public void removeSongsByPosition(int[] songs) throws MPDServerException {
        java.util.Arrays.sort(songs);
        for (int i = songs.length - 1; i >= 0; i--) {
            String[] args = new String[1];
            args[0] = Integer.toString(songs[i]);
            this.mpd.getMpdConnection().queueCommand(MPD_CMD_PLAYLIST_REMOVE, args);
        }
        this.mpd.getMpdConnection().sendCommandQueue();

        for (int i = songs.length - 1; i >= 0; i--) {
            list.removeByPosition(songs[i]);
        }
    }

    /**
     * Removes entries from playlist.
     * @param songIds entries Ids.
     * @throws MPDServerException if an error occur while contacting server.
     */
    public void removeSongs(int[] songIds) throws MPDServerException {

        for (int i = songIds.length - 1; i >= 0; i--) {
            String[] args = new String[1];
            args[0] = Integer.toString(songIds[i]);
            this.mpd.getMpdConnection().queueCommand(MPD_CMD_PLAYLIST_REMOVE_ID, args);
        }
        this.mpd.getMpdConnection().sendCommandQueue();

        for (int i = songIds.length - 1; i >= 0; i--) {
            list.removeBySongId(songIds[i]);
        }
    }

    /**
     * Save playlist file.
     * @param file playlist filename without .m3u extension.
     * @throws MPDServerException if an error occur while contacting server.
     */
    public void save(String file) throws MPDServerException {
        String[] args = new String[1];
        args[0] = file;
        this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_SAVE, args);
    }

    /**
     * Shuffles playlist content.
     * @throws MPDServerException if an error occur while contacting server.
     */
    public void shuffle() throws MPDServerException {
        this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_SHUFFLE);
    }

    /**
     * Retrieves playlist size. Operates on local copy of playlist, may not reflect server's current playlist. You may
     * call refresh() before calling size().
     * @return playlist size.
     */
    public int size() {
        return list.size();
    }

    /**
     * Swap positions of song1 and song2.
     * @param song1 position of song1 in playlist.
     * @param song2 position of song2 in playlist
     * @throws MPDServerException if an error occur while contacting server.
     * @deprecated use <code>swap</code>.
     * @see #swap(int, int)
     */
    public void swapByPosition(int song1, int song2) throws MPDServerException {
        String[] args = new String[2];
        args[0] = Integer.toString(song1);
        args[0] = Integer.toString(song2);
        this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_SWAP, args);
        this.refresh();
    }

    /**
     * Swap positions of song1 and song2.
     * @param song1Id id of song1 in playlist.
     * @param song2Id id of song2 in playlist.
     * @throws MPDServerException if an error occur while contacting server.
     */
    public void swap(int song1Id, int song2Id) throws MPDServerException {
        String[] args = new String[2];
        args[0] = Integer.toString(song1Id);
        args[1] = Integer.toString(song2Id);
        this.mpd.getMpdConnection().sendCommand(MPD_CMD_PLAYLIST_SWAP_ID, args);
        this.refresh();
    }

    /**
     * Retrieves all songs as an <code>List</code> of <code>Music</code>.
     * @return all songs as an <code>List</code> of <code>Music</code>.
     * @see Music
     */
    public List<Music> getMusics() {
        return this.list.getMusics();
    }

    /**
     * Retrieves a string representation of the object.
     * @return a string representation of the object.
     * @see java.lang.Object#toString()
     */
    public String toString() {
        StringBuffer sb = new StringBuffer();
        for (Music m : list.getMusics()) {
            sb.append(m.toString() + "\n");
        }
        return sb.toString();
    }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.