org.jajuk.services.dj.TransitionDigitalDJ.java Source code

Java tutorial

Introduction

Here is the source code for org.jajuk.services.dj.TransitionDigitalDJ.java

Source

/*
 *  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.services.dj;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.jajuk.base.File;
import org.jajuk.base.FileManager;
import org.jajuk.base.Genre;
import org.jajuk.util.Const;
import org.jajuk.util.UtilFeatures;
import org.jajuk.util.filters.JajukPredicates;

/**
 * Type description.
 */
public class TransitionDigitalDJ extends DigitalDJ {
    /** List of transitions, need to be a list, not a set for offset. */
    private List<Transition> transitions;

    /**
     * The Constructor.
     * 
     * @param sID 
     */
    public TransitionDigitalDJ(String sID) {
        super(sID);
        this.transitions = new ArrayList<Transition>(10);
    }

    /**
     * Gets the transitions.
     * 
     * @return DJ transitions
     */
    public List<Transition> getTransitions() {
        return this.transitions;
    }

    /**
     * Delete a transition at given offset.
     * 
     * @param offset 
     */
    public void deleteTransition(int offset) {
        this.transitions.remove(offset);
    }

    /**
     * Add a transition.
     * 
     * @param transition 
     * @param offset 
     */
    public void addTransition(Transition transition, int offset) {
        this.transitions.add(offset, transition);
    }

    /**
     * Gets the transition.
     * 
     * @param ambience 
     * 
     * @return transition mapping this FROM ambience or null if none maps it
     */
    public Transition getTransition(Ambience ambience) {
        for (Transition transition : transitions) {
            if (CollectionUtils.containsAny(transition.getFrom().getGenres(), ambience.getGenres())) {
                return transition;
            }
        }
        return null;
    }

    /*
     * Generate the playlist @return the playlist
     */
    /* (non-Javadoc)
     * @see org.jajuk.services.dj.DigitalDJ#generatePlaylist()
     */
    @Override
    public List<File> generatePlaylist() {
        List<File> out = new ArrayList<File>(500);
        // get a global shuffle selection
        List<File> global = FileManager.getInstance().getGlobalShufflePlaylist();
        // Select by rate if needed
        filterFilesByRate(global);
        // None element, leave
        if (global.size() == 0) {
            return out;
        }
        // Build a ambience -> files map
        Map<Ambience, List<File>> hmAmbienceFiles = getAmbienceFilesList(global);
        // compute number of items to add
        int items = Math.min(global.size(), Const.NB_TRACKS_ON_ACTION);
        if (!bUnicity && items < Const.MIN_TRACKS_NUMBER_WITHOUT_UNICITY) {
            // under a limit, if collection is too small and no unicity, use
            // several times the same files
            items = Const.MIN_TRACKS_NUMBER_WITHOUT_UNICITY;
        }
        // Get first track
        for (File file : global) {
            if (transitions.get(0).getFrom().getGenres().contains(file.getTrack().getGenre())) {
                out.add(file);
                // Unicity in selection, remove it from this ambience
                if (bUnicity) {
                    List<File> files = hmAmbienceFiles.get(getAmbience(file.getTrack().getGenre()));
                    files.remove(file);
                }
                items--;
                break;
            }
        }
        // none matching track? return
        if (out.size() == 0) {
            return out;
        }
        // initialize current ambience with first track ambience (can be null for
        // unsorted tracks)
        Ambience currentAmbience = getAmbience(out.get(0).getTrack().getGenre());
        // start transition applying
        while (items > 0) {
            // A genre can be in only one transition
            Transition currentTransition = getTransition(currentAmbience);
            List<File> files = hmAmbienceFiles.get(currentAmbience);
            int nbTracks = 2;
            if (currentTransition != null) {
                nbTracks = currentTransition.getNbTracks();
            }
            // We remove one item as it has already been added through the first track
            if (out.size() == 1) {
                nbTracks--;
            }
            if (files != null && files.size() >= nbTracks) {
                for (int i = 0; i < nbTracks && files.size() > 0; i++) {
                    File file = UtilFeatures.getShuffleItem(files);
                    out.add(file);
                    items--;
                    // Unicity in selection, remove it from this ambience
                    if (bUnicity) {
                        files.remove(file);
                    }
                }
            } else { // no more tracks for this ambience ? leave
                // finally ensure that we don't select more than the max number of tracks
                filterFilesByMaxTrack(out);
                return out;
            }
            if (currentTransition != null) {
                currentAmbience = currentTransition.getTo();
            } else {
                break;
            }
        }
        // finally ensure that we don't select more than the max number of tracks
        filterFilesByMaxTrack(out);
        return out;
    }

    /**
     * Returns a map ambience -> set of files.
     * 
     * @param global initial set of files to consider
     * 
     * @return a map ambience -> set of files
     */
    @SuppressWarnings("unchecked")
    private Map<Ambience, List<File>> getAmbienceFilesList(List<File> global) {
        // Create a map ambience -> set of files
        Map<Ambience, List<File>> hmAmbienceFiles = new HashMap<Ambience, List<File>>(5);
        // For performance, we find unique ambiences in from and to transitions
        Set<Ambience> ambiences = new HashSet<Ambience>(5);
        for (Transition tr : transitions) {
            ambiences.add(tr.getFrom());
            ambiences.add(tr.getTo());
        }
        // Fill null key
        hmAmbienceFiles.put(null, (List<File>) ((ArrayList<File>) global).clone());
        // Fill all ambiences
        for (Ambience ambience : ambiences) {
            List<File> all = (List<File>) ((ArrayList<File>) global).clone();
            CollectionUtils.filter(all, new JajukPredicates.AmbiencePredicate(ambience));
            hmAmbienceFiles.put(ambience, all);
        }
        return hmAmbienceFiles;
    }

    /**
     * Gets the ambience.
     * 
     * @param genre 
     * 
     * @return ambience associated with a genre known in transitions or null if
     * none
     */
    private Ambience getAmbience(Genre genre) {
        for (Transition transition : transitions) {
            if (transition.getFrom().getGenres().contains(genre)) {
                return transition.getFrom();
            }
        }
        return null;
    }

    /**
     * (non-Javadoc).
     * 
     * @return the string
     * 
     * @see dj.DigitalDJ#toXML()
     */
    @Override
    public String toXML() {
        StringBuilder sb = new StringBuilder(2000);
        sb.append(toXMLGeneralParameters());
        sb.append("\t<" + Const.XML_DJ_TRANSITIONS + ">\n");
        for (Transition transition : transitions) {
            sb.append("\t\t<" + Const.XML_DJ_TRANSITION + " " + Const.XML_DJ_FROM + "='"
                    + transition.getFrom().toXML() + "' " + Const.XML_DJ_TO + "='" + transition.getTo().toXML()
                    + "' " + Const.XML_DJ_NUMBER + "='" + transition.getNbTracks() + "'/>\n");
        }
        sb.append("\t</" + Const.XML_DJ_TRANSITIONS + ">\n");
        sb.append("</" + Const.XML_DJ_DJ + ">\n");
        return sb.toString();
    }

    /**
     * Sets the transitions.
     * 
     * @param transitions the new transitions
     */
    public void setTransitions(List<Transition> transitions) {
        this.transitions = transitions;
    }
}