/*
* Jampa
* Copyright (C) 2008-2009 J. Devauchelle and contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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.
*/
package org.jampa.controllers.core;
import java.io.File;
import java.io.FilenameFilter;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.util.Util;
import org.eclipse.swt.widgets.Display;
import org.jampa.controllers.Controller;
import org.jampa.controllers.events.EventConstants;
import org.jampa.gui.runnables.DirectoryAdder;
import org.jampa.gui.runnables.DiskItemAdder;
import org.jampa.gui.runnables.LibraryAdder;
import org.jampa.gui.runnables.PlaylistChecker;
import org.jampa.logging.Log;
import org.jampa.model.IAudioItem;
import org.jampa.model.IPlaylist;
import org.jampa.model.comparators.PlaylistComparator;
import org.jampa.model.comparators.PodcastsComparator;
import org.jampa.model.disk.DirectoryItem;
import org.jampa.model.disk.FileItem;
import org.jampa.model.disk.IDiskItem;
import org.jampa.model.library.ILibraryItem;
import org.jampa.model.library.TitleItem;
import org.jampa.model.playlists.AudioItem;
import org.jampa.model.playlists.Playlist;
import org.jampa.model.podcasts.Podcast;
import org.jampa.model.podcasts.PodcastItem;
import org.jampa.net.podcast.PodcastItemDownloaderJob;
import org.jampa.preferences.PreferenceConstants;
import org.jampa.utils.Constants;
import org.jampa.utils.SystemUtils;
/**
* Playlist controller
* Handle playlists list.
* Play files.
* @author jerem
*
*/
public class PlaylistController {
private Map<String, Playlist> _items;
private Map<String, Playlist> _itemsToDelete;
private Map<String, Podcast> _podcastItems;
private Map<String, Podcast> _podcastItemsToDelete;
private IAudioItem _currentAudioItem;
private IPlaylist _currentPlaylist;
private int _playlistListSortDirection = 0;
private int _playlistListSortColumn = 0;
private int _podcastSortDirection = 0;
private int _podcastSortColumn = 0;
public PlaylistController() {
_items = new Hashtable<String, Playlist>();
_itemsToDelete = new Hashtable<String, Playlist>();
_podcastItems = new Hashtable<String, Podcast>();
_podcastItemsToDelete = new Hashtable<String, Podcast>();
Log.getInstance(PlaylistController.class).debug("PlaylistController initialized."); //$NON-NLS-1$
}
/**
* Performs action when application close.
* Stop playback and remove listeners in the case of the output reader try to update the ui while closing (Tricky bug).
*/
public void onApplicationClose() {
if (Controller.getInstance().getEngine().isPlaying()) {
Controller.getInstance().getEngine().stopPlayback();
}
}
public void importPlaylist(String playlistName, String fileName) {
if (!_items.containsKey(playlistName)) {
Playlist newPlaylist = new Playlist(playlistName, fileName);
newPlaylist.setPosition(_items.size());
newPlaylist.updateFileName();
_items.put(playlistName, newPlaylist);
Controller.getInstance().getEventController().firePlaylistChange(EventConstants.EVT_ADD_PLAYLIST, null, newPlaylist);
}
}
/**
* Add the specified playlist to the list.
* @param playlistName The playlist name.
* @param fileName The associated file.
* @return True if the playlist does not already exists, False otherwise.
*/
private boolean addPlaylist(String playlistName, String fileName) {
if (!_items.containsKey(playlistName)) {
Playlist newPlaylist = new Playlist(playlistName, fileName);
_items.put(playlistName, newPlaylist);
return true;
} else
return false;
}
/**
* Add an empty playlist to the list.
* @param playlistName The playlist name.
* @return True if the playlist does not already exists, False otherwise.
*/
public boolean addEmptyPlaylist(String playlistName) {
if (!_items.containsKey(playlistName)) {
Playlist newPlaylist = new Playlist(playlistName);
newPlaylist.setDate(new Date());
newPlaylist.setPosition(_items.size());
_items.put(playlistName, newPlaylist);
Controller.getInstance().getEventController().firePlaylistChange(EventConstants.EVT_ADD_PLAYLIST, null, newPlaylist);
return true;
} else
return false;
}
public boolean renamePlaylist(String newPlaylistName, String oldPlaylistName) {
if (_items.containsKey(oldPlaylistName)) {
if (duplicatePlaylist(newPlaylistName, oldPlaylistName)) {
removePlaylist(oldPlaylistName);
return true;
} else {
return false;
}
} else
return false;
}
/**
* Copy a playlist.
* @param playlistName The new play list name.
* @param originalPlaylist The playlist to be copied.
* @return True if the playlist does not already exists, False otherwise.
*/
public boolean duplicatePlaylist(String playlistName, String originalPlaylist) {
if (!_items.containsKey(playlistName)) {
Playlist newPlaylist = new Playlist(playlistName);
newPlaylist.setDate(new Date());
newPlaylist.setPosition(_items.size());
_items.put(playlistName, newPlaylist);
Playlist originalPL = _items.get(originalPlaylist);
Iterator<AudioItem> iter = originalPL.getAudioList().iterator();
AudioItem item;
while (iter.hasNext()) {
item = new AudioItem(iter.next());
newPlaylist.addAudioItem(item);
}
Controller.getInstance().getEventController().firePlaylistChange(EventConstants.EVT_ADD_PLAYLIST, null, newPlaylist);
return true;
} else
return false;
}
/**
* Remove a playlist from the list. Insert it into the list of playlist that need to be deleted.
* @param playlistName
*/
public void removePlaylist(String playlistName) {
if (_items.containsKey(playlistName)) {
Playlist playlist;
playlist = _items.remove(playlistName);
if (playlist.hasAudioItemPlaying()) {
stopPlayback();
}
if (!_itemsToDelete.containsKey(playlistName)) {
_itemsToDelete.put(playlistName, playlist);
}
Controller.getInstance().getEventController().firePlaylistChange(EventConstants.EVT_REMOVE_PLAYLIST, null, null);
}
}
/**
* Remove all items in the specified playlist.
* @param playlistName
*/
public void clearPlaylist(String playlistName) {
if (_items.containsKey(playlistName)) {
AudioItem item;
Playlist playlist = _items.get(playlistName);
Iterator<AudioItem> iter = playlist.getAudioList().iterator();
while (iter.hasNext()) {
item = iter.next();
if (item.isBoPlaying()) {
stopPlayback();
break;
}
}
playlist.getAudioList().clear();
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_ITEM_CHANGE_IN_PLAYLIST, null, null);
} else
Log.getInstance(PlaylistController.class).info("Playlist not found : " + playlistName); //$NON-NLS-1$
}
/**
* Remove the specified AudioItem from the specified playlist.
* @see AudioItem
* @param playlistName
* @param item
*/
public void removeFromPlaylist(String playlistName, AudioItem item) {
if (_items.containsKey(playlistName)) {
if (item.isBoPlaying())
stopPlayback();
_items.get(playlistName).removeAudioItem(item);
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_ITEM_CHANGE_IN_PLAYLIST, null, null);
} else
Log.getInstance(PlaylistController.class).info("Playlist not found : " + playlistName); //$NON-NLS-1$
}
public void moveTitleAtIndex(String playlistName, int index, AudioItem item) {
if (_items.containsKey(playlistName)) {
Log.getInstance(PlaylistController.class).debug("Move item " + item.getFileName() + " to index: " + index); //$NON-NLS-1$ //$NON-NLS-2$
Playlist playlist = _items.get(playlistName);
playlist.moveItemAtIndex(index, item);
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_ITEM_CHANGE_IN_PLAYLIST, null, null);
} else
Log.getInstance(PlaylistController.class).info("Playlist not found : " + playlistName); //$NON-NLS-1$
}
/**
* Move the specified AudioItem down in the specified playlist.
* @param playlistName
* @param item
*/
public void moveTitleDown(String playlistName, AudioItem item) {
if (_items.containsKey(playlistName)) {
Playlist playlist = _items.get(playlistName);
playlist.moveItemDown(item);
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_ITEM_CHANGE_IN_PLAYLIST, null, null);
} else
Log.getInstance(PlaylistController.class).info("Playlist not found : " + playlistName); //$NON-NLS-1$
}
/**
* Move the specified AudioItem up in the specified playlist.
* @param playlistName
* @param item
*/
public void moveTitleUp(String playlistName, AudioItem item) {
if (_items.containsKey(playlistName)) {
Playlist playlist = _items.get(playlistName);
playlist.moveItemUp(item);
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_ITEM_CHANGE_IN_PLAYLIST, null, null);
} else
Log.getInstance(PlaylistController.class).info("Playlist not found : " + playlistName); //$NON-NLS-1$
}
public void playPlaylist(String playlistName) {
if (_items.containsKey(playlistName)) {
Playlist playlist = _items.get(playlistName);
IAudioItem item = playlist.getAudioItemByIndex(0);
if (item != null) {
playFile(playlist, item);
}
} else
Log.getInstance(PlaylistController.class).info("Playlist not found : " + playlistName); //$NON-NLS-1$
}
public void playFile(String playlistName, String fileName) {
if (_items.containsKey(playlistName)) {
Playlist playlist = _items.get(playlistName);
AudioItem item = playlist.getAudioItemByPath(fileName);
if (item != null) {
playFile(playlist, item);
}
} else
Log.getInstance(PlaylistController.class).info("Playlist not found : " + playlistName); //$NON-NLS-1$
}
/**
* Play the specified AudioItem from the specified playlist.
* @param playlistName
* @param item
*/
public void playFile(String playlistName, IAudioItem item) {
if (_items.containsKey(playlistName)) {
playFile(_items.get(playlistName), item);
} else
Log.getInstance(PlaylistController.class).info("Playlist not found : " + playlistName); //$NON-NLS-1$
}
/**
* Play the specified AudioItem from the specified Playlist.
* @param playlist
* @param item
*/
public void playFile(IPlaylist playlist, IAudioItem item) {
playFile(playlist, item, false);
}
private void playFile(IPlaylist playlist, IAudioItem item, boolean fromNext) {
if ((item instanceof PodcastItem) &&
(Controller.getInstance().getPreferenceStore().getBoolean(PreferenceConstants.PODCAST_DOWNLOAD_BEFORE_PLAY))) {
if (!((PodcastItem) item).doesTemporaryFileExists()) {
PodcastItemDownloaderJob downloadJob = new PodcastItemDownloaderJob(playlist, (PodcastItem) item);
downloadJob.schedule();
// If we come from playNextInPlaylist(), and we start downloading the next item,
// we must stop playback in order to update icons state...
if (fromNext) {
stopPlayback();
}
return;
}
}
IAudioItem oldItem = _currentAudioItem;
if (oldItem != null)
oldItem.setBoPlaying(false);
_currentPlaylist = playlist;
_currentAudioItem = item;
_currentAudioItem.setBoPlaying(true);
Controller.getInstance().getEngine().playFile(_currentAudioItem);
if (_currentAudioItem instanceof PodcastItem) {
((PodcastItem) _currentAudioItem).setRead(true);
}
if (playlist != null) {
Controller.getInstance().getStatisticsController().notifyPlay(playlist.getName(), _currentAudioItem);
}
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_PLAY_NEW_AUDIO_ITEM, null, _currentAudioItem);
}
/**
* Pause the playback.
*/
public void pausePlayback() {
Controller.getInstance().getEngine().pausePlayback();
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_PAUSE_PLAYBACK, null, _currentAudioItem);
}
/**
* Return a random index between 0 and maxValue - 1, except current value.
* @param currentValue
* @param maxValue
* @return A random index
*/
private int getRandomIndex(int currentValue, int maxValue) {
Random generator = new Random();
int result = currentValue;
while (result == currentValue) {
result = generator.nextInt(maxValue);
}
return result;
}
/**
* Play next file in the playing playlist.
* This method take care of the current playing mode.
* @param stopIfNoNext If True, call stopPlayback() in order to reset the playing informations.
*/
public void playNextInPlaylist(boolean stopIfNoNext) {
if (_currentPlaylist != null) {
int index = _currentPlaylist.getAudioItemIndex(_currentAudioItem);
switch (Controller.getInstance().getPreferenceStore().getInt(PreferenceConstants.PLAY_MODE)) {
case 0 : index++; if (index > _currentPlaylist.getPlaylistMaxIndex()) { index = -1; } break;
case 1 : index++; if (index > _currentPlaylist.getPlaylistMaxIndex()) { index = 0; } break;
case 2 : if (_currentPlaylist.getPlaylistMaxIndex() > 0) { index = getRandomIndex(index, _currentPlaylist.getPlaylistMaxIndex() + 1); } else { index = 0; }; break;
}
if (index >= 0) {
playFile(_currentPlaylist, _currentPlaylist.getAudioItemByIndex(index), true);
} else {
if (stopIfNoNext)
stopPlayback();
}
} else {
stopPlayback();
}
}
/**
* Play previous file in the playing playlist.
*/
public void playPreviousInPlaylist() {
if (_currentPlaylist != null) {
int index = _currentPlaylist.getAudioItemIndex(_currentAudioItem);
if (index > 0) {
index--;
playFile(_currentPlaylist, _currentPlaylist.getAudioItemByIndex(index));
}
}
}
/**
* Set the playing position.
* @param position
*/
public void setPosition(int position) {
Controller.getInstance().getEngine().setPosition(position);
}
/**
* Stop the playback.
* Send an EVT_STOP_PLAYBACK event.
*/
public void stopPlayback() {
if (Controller.getInstance().getEngine().isPlaying()) {
Controller.getInstance().getEngine().stopPlayback();
_currentAudioItem.setBoPlaying(false);
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_STOP_PLAYBACK, _currentAudioItem, null);
_currentPlaylist = null;
_currentAudioItem = null;
}
}
/**
* Check if a playlist exists in the list.
* Under Windows, verification is made case-unsensitive.
* @param playlistName
* @return True if the playlist exists, False otherwise.
*/
public boolean doesPlaylistExist(String playlistName) {
if (Util.isWindows()) {
boolean result = false;
Iterator<String> iter = _items.keySet().iterator();
while ((!result) &&
(iter.hasNext())) {
if (iter.next().equalsIgnoreCase(playlistName)) {
result = true;
}
}
return result;
} else {
return _items.containsKey(playlistName);
}
}
/**
* Get a Playlist by its name.
* @param playlistName
* @return The Playlist found or null.
*/
public Playlist getPlaylistByName(String playlistName) {
if (_items.containsKey(playlistName)) {
return _items.get(playlistName);
} else
return null;
}
private void updatePlaylistPosition(List<Playlist> list) {
int index = 0;
Playlist item;
Iterator<Playlist> iter = list.iterator();
while (iter.hasNext()) {
item = iter.next();
if (_items.containsKey(item.getName())) {
_items.get(item.getName()).setPosition(index);
index++;
}
}
}
public void movePlaylist(Playlist playlist, int toIndex) {
Playlist item;
int fromIndex = playlist.getPosition();
boolean directionDown = (toIndex > fromIndex);
Set<String> keySet = _items.keySet();
Iterator<String> iter = keySet.iterator();
while (iter.hasNext()) {
item = _items.get(iter.next());
if (item != playlist) {
if (directionDown) {
if ((item.getPosition() > fromIndex) &&
(item.getPosition() <= toIndex)) {
item.setPosition(item.getPosition() - 1);
}
} else {
if ((item.getPosition() >= toIndex) &&
(item.getPosition() < fromIndex)) {
item.setPosition(item.getPosition() + 1);
}
}
}
}
playlist.setPosition(toIndex);
sortPlaylistList(0, 0);
}
/**
* Get a sorted array of all the Playlist.
* @return A sorted array of Playlist
*/
public Object[] getPlaylistList() {
List<Playlist> tmpList = new ArrayList<Playlist>();
Set<String> keys = _items.keySet();
Iterator<String> iter = keys.iterator();
Playlist item;
while (iter.hasNext()) {
item = _items.get(iter.next());
if (!item.getName().equals(Constants.DEFAULT_PLAYLIST_ID)) {
tmpList.add(item);
}
}
Collections.sort(tmpList, new PlaylistComparator(_playlistListSortColumn, _playlistListSortDirection));
updatePlaylistPosition(tmpList);
return tmpList.toArray(new Playlist[0]);
}
/**
* Get a sorted array of the AudioItem from the specified playlist.
* @param playlistName
* @return A sorted array of AudioItem
*/
public Object[] getPlaylistData(String playlistName) {
if (_items.containsKey(playlistName)) {
return _items.get(playlistName).getAudioList().toArray(new AudioItem[0]);
} else
return null;
}
/**
* Sort the AudioItem of the specified Playlist in the specified mode.
* @see org.jampa.model.comparators.AudioItemComparator
* @param playlist
* @param mode
*/
public void sortPlaylist(Playlist playlist, int mode) {
playlist.sortPlaylist(mode);
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_SORT_PLAYLIST, null, null);
}
private void sortPlaylistList(int column, int direction) {
_playlistListSortDirection = direction;
_playlistListSortColumn = column;
Controller.getInstance().getEventController().firePlaylistChange(EventConstants.EVT_SORT_PLAYLIST_LIST, null, null);
}
/**
* Invert the current sort direction.
* Trigger an EVT_SORT_PLAYLIST_LIST event.
* Does NOT perform the sort, it will be done by getPlaylistList() when the view refresh because of the event.
*/
public void sortPlaylistList(int column) {
if (column == _playlistListSortColumn) {
switch(_playlistListSortDirection) {
case 0 : _playlistListSortDirection = 1; break;
case 1 : _playlistListSortDirection = 0; break;
default : _playlistListSortDirection = 0;
}
}
sortPlaylistList(column, _playlistListSortDirection);
}
/**
* Internal method : add the specified file to the specified playlist.
* Does NOT perform playlist existence verification.
* Does NOT notify listeners.
*
* @param playlistName
* @param fileName
*/
private void internalAddFileToPlaylist(String playlistName, String fileName, boolean isRemovable, int insertionIndex) {
Playlist playlist = _items.get(playlistName);
if (insertionIndex == -1) {
playlist.addAudioItem(new AudioItem(fileName, true, isRemovable));
} else {
playlist.insertAudioItem(new AudioItem(fileName, true, isRemovable), insertionIndex);
}
}
/**
* Add the specified FileItem to the specified playlist.
* Perform playlist existence verification.
* Notify listeners.
*
* @param playlistName
* @param fileItem
* @param playFile Play the file after having enqueued it.
*/
public void addFileToPlaylist(String playlistName, FileItem fileItem, boolean playFile) {
addFileToPlaylist(playlistName, fileItem, playFile, true);
}
/**
* Add the specified FileItem to the specified playlist.
* Perform playlist existence verification.
* Notify listeners.
*
* @param playlistName
* @param fileItem
* @param playFile Play the file after having enqueued it.
* @param notify Notify listeners
*/
public void addFileToPlaylist(String playlistName, FileItem fileItem, boolean playFile, boolean notify) {
addFileToPlaylist(playlistName, fileItem, playFile, notify, -1);
}
public void addFileToPlaylist(String playlistName, FileItem fileItem, boolean playFile, boolean notify, int insertionIndex) {
boolean isRemovable = ((fileItem.getParent() != null) && (fileItem.getParent().getDirType() == DirectoryItem.DirectoryType.REMOVABLE));
addFileToPlaylist(playlistName, fileItem.getFileName(), playFile, notify, isRemovable, insertionIndex);
}
/**
* Add the specified file to the specified playlist.
* Perform playlist existence verification.
* Notify listeners.
*
* @param playlistName
* @param fileName
* @param playFile Play the file after having enqueued it.
*/
public void addFileToPlayList(String playlistName, String fileName, boolean playFile, boolean isRemovable) {
addFileToPlaylist(playlistName, fileName, playFile, true, isRemovable, -1);
}
public void addFileToPlayList(String playlistName, String fileName, boolean playFile, boolean isRemovable, int insertionIndex) {
addFileToPlaylist(playlistName, fileName, playFile, true, isRemovable, insertionIndex);
}
/**
* Add the specified file to the specified playlist.
* Perform playlist existence verification.
*
* @param playlistName
* @param fileName
* @param playFile Play the file after having enqueued it.
* @param notify Notify listeners
*/
private void addFileToPlaylist(String playlistName, String fileName, boolean playFile, boolean notify, boolean isRemovable, int insertionIndex) {
if (_items.containsKey(playlistName)) {
internalAddFileToPlaylist(playlistName, fileName, isRemovable, insertionIndex);
if (playFile) {
Playlist playlist = getPlaylistByName(playlistName);
if (playlist != null) {
AudioItem item = playlist.getAudioItemByPath(fileName);
if (item != null) {
playFile(playlistName, item);
}
}
}
if (notify) {
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_ITEM_CHANGE_IN_PLAYLIST, null, null);
}
} else
Log.getInstance(PlaylistController.class).info("Playlist not found : " + playlistName); //$NON-NLS-1$
}
/**
* Add the specified items to the specified playlist.
* Trigger an EVT_ITEM_CHANGE_IN_PLAYLIST event.
* @param playlistName
* @param libraryItem
* @param playFirst Play the first file after having enqueued artist
*/
public void addItemToPlaylist(String playlistName, ILibraryItem libraryItem, boolean playFirst) {
addItemToPlaylist(playlistName, libraryItem, playFirst, -1);
}
public void addItemToPlaylist(String playlistName, ILibraryItem libraryItem, boolean playFirst, int insertionIndex) {
if (_items.containsKey(playlistName)) {
if (libraryItem != null) {
LibraryAdder adder = new LibraryAdder(playlistName, libraryItem, insertionIndex);
ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getDefault().getActiveShell());
try {
dialog.run(true, true, adder);
} catch (InvocationTargetException e) {
Log.getInstance(PlaylistController.class).error(e.getMessage());
} catch (InterruptedException e) {
Log.getInstance(PlaylistController.class).error(e.getMessage());
}
if (playFirst) {
if (adder.getFirstItem() != null) {
Playlist playlist = getPlaylistByName(playlistName);
if (playlist != null) {
AudioItem audioItem = playlist.getAudioItemByPath(((TitleItem) adder.getFirstItem()).getFilePath());
if (audioItem != null) {
playFile(playlistName, audioItem);
}
}
}
}
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_ITEM_CHANGE_IN_PLAYLIST, null, null);
} else
Log.getInstance(PlaylistController.class).info("Null ILibraryItem."); //$NON-NLS-1$
} else
Log.getInstance(PlaylistController.class).info("Playlist not found : " + playlistName); //$NON-NLS-1$
}
public void addDiskItemsToPlaylist(String playlistName, List<IDiskItem> items, boolean playFirst) {
addDiskItemsToPlaylist(playlistName, items, playFirst, -1);
}
public void addDiskItemsToPlaylist(String playlistName, List<IDiskItem> items, boolean playFirst, int insertionIndex) {
if (_items.containsKey(playlistName)) {
DiskItemAdder adder = new DiskItemAdder(playlistName, items, insertionIndex);
ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getDefault().getActiveShell());
try {
dialog.run(true, true, adder);
} catch (InvocationTargetException e) {
Log.getInstance(PlaylistController.class).error(e.getMessage());
} catch (InterruptedException e) {
Log.getInstance(PlaylistController.class).error(e.getMessage());
}
if (playFirst) {
Playlist playlist = getPlaylistByName(playlistName);
if (playlist != null) {
AudioItem item = playlist.getAudioItemByPath(adder.getFirstFileItem().getFileName());
if (item != null) {
playFile(playlistName, item);
}
}
}
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_ITEM_CHANGE_IN_PLAYLIST, null, null);
} else
Log.getInstance(PlaylistController.class).info("Playlist not found : " + playlistName); //$NON-NLS-1$
}
/**
* Add the specified DirectoryItem to the specified playlist.
* Perform playlist existence verification.
* Notify listeners.
*
* @param playlistName
* @param directoryItem
* @param playFirst Play the first file after having enqueued directory
*/
public void addDirectoryToPlaylist(String playlistName, DirectoryItem directoryItem, boolean playFirst) {
if (_items.containsKey(playlistName)) {
DirectoryAdder adder = new DirectoryAdder(playlistName, directoryItem);
ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getDefault().getActiveShell());
try {
dialog.run(true, true, adder);
} catch (InvocationTargetException e) {
Log.getInstance(PlaylistController.class).error(e.getMessage());
} catch (InterruptedException e) {
Log.getInstance(PlaylistController.class).error(e.getMessage());
}
if (playFirst) {
Playlist playlist = getPlaylistByName(playlistName);
if (playlist != null) {
AudioItem item = playlist.getAudioItemByPath(directoryItem.getFirstFileItem().getFileName());
if (item != null) {
playFile(playlistName, item);
}
}
}
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_ITEM_CHANGE_IN_PLAYLIST, null, null);
} else
Log.getInstance(PlaylistController.class).info("Playlist not found : " + playlistName); //$NON-NLS-1$
}
public HashMap<AudioItem, String> doCheckPlaylists() {
Log.getInstance(Controller.class).info("Start checking playlists."); //$NON-NLS-1$
PlaylistChecker playlistChecker = new PlaylistChecker();
ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getDefault().getActiveShell());
try {
dialog.run(true, true, playlistChecker);
} catch (InvocationTargetException e) {
Log.getInstance(Controller.class).error(e.getMessage());
} catch (InterruptedException e) {
Log.getInstance(Controller.class).error(e.getMessage());
}
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_ITEM_CHANGE_IN_PLAYLIST, null, null);
Log.getInstance(PlaylistController.class).info("End of playlists check."); //$NON-NLS-1$
return playlistChecker.getResults();
}
/**
* Import all old m3u playlists from the playlist directory, and delete them after.
*/
private void importOldPlaylists() {
File playlistDir = new File(SystemUtils.playlistDirectory);
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return !name.startsWith(".") && name.endsWith(SystemUtils.playlistM3UExtension); //$NON-NLS-1$
}
};
String name;
int lastIndex;
File deleteFile;
String[] files = playlistDir.list(filter);
for (int i = 0; i < files.length; i++) {
lastIndex = files[i].lastIndexOf(SystemUtils.playlistM3UExtension);
if (lastIndex == -1)
lastIndex = files[i].length();
name = files[i].substring(0, lastIndex);
importPlaylist(name, SystemUtils.playlistDirectory + files[i]);
deleteFile = new File(SystemUtils.playlistDirectory + files[i]);
deleteFile.delete();
}
}
public Podcast getPodcastByName(String podcastName) {
if (_podcastItems.containsKey(podcastName)) {
return _podcastItems.get(podcastName);
} else
return null;
}
public void addPodcast(String name, String url) {
Podcast podcast = new Podcast(name, "", url, "");
podcast.setPosition(_podcastItems.size());
podcast.download();
podcast.parseData();
_podcastItems.put(podcast.getName(), podcast);
Controller.getInstance().getEventController().firePlaylistChange(EventConstants.EVT_ADD_PLAYLIST, null, name);
}
public boolean renamePodcast(String newPodcastName, String oldPodcastName) {
if (_podcastItems.containsKey(oldPodcastName)) {
Podcast newPodcast = new Podcast(_podcastItems.get(oldPodcastName));
newPodcast.setName(newPodcastName);
_podcastItems.put(newPodcastName, newPodcast);
removePodcast(oldPodcastName);
Controller.getInstance().getEventController().firePlaylistChange(EventConstants.EVT_ADD_PLAYLIST, null, newPodcast);
return true;
} else {
return false;
}
}
public void removePodcast(String podcastName) {
if (_podcastItems.containsKey(podcastName)) {
Podcast podcast;
podcast = _podcastItems.remove(podcastName);
if (podcast.hasAudioItemPlaying()) {
stopPlayback();
}
if (!_podcastItemsToDelete.containsKey(podcastName)) {
_podcastItemsToDelete.put(podcastName, podcast);
}
Controller.getInstance().getEventController().firePlaylistChange(EventConstants.EVT_REMOVE_PLAYLIST, null, null);
}
}
public Object[] getPodcastData(String podcastName) {
if (_podcastItems.containsKey(podcastName)) {
return _podcastItems.get(podcastName).getPodcastList().toArray(new PodcastItem[0]);
} else
return null;
}
public List<Podcast> getPodcastListAsList() {
List<Podcast> tmpList = new ArrayList<Podcast>();
Set<String> keys = _podcastItems.keySet();
Iterator<String> iter = keys.iterator();
Podcast item;
while (iter.hasNext()) {
item = _podcastItems.get(iter.next());
tmpList.add(item);
}
return tmpList;
}
private void updatePodcastsPosition(List<Podcast> list) {
int index = 0;
Podcast item;
Iterator<Podcast> iter = list.iterator();
while (iter.hasNext()) {
item = iter.next();
if (_podcastItems.containsKey(item.getName())) {
_podcastItems.get(item.getName()).setPosition(index);
index++;
}
}
}
public void movePodcast(Podcast podcast, int toIndex) {
Podcast item;
int fromIndex = podcast.getPosition();
boolean directionDown = (toIndex > fromIndex);
Set<String> keySet = _podcastItems.keySet();
Iterator<String> iter = keySet.iterator();
while (iter.hasNext()) {
item = _podcastItems.get(iter.next());
if (item != podcast) {
if (directionDown) {
if ((item.getPosition() > fromIndex) &&
(item.getPosition() <= toIndex)) {
item.setPosition(item.getPosition() - 1);
}
} else {
if ((item.getPosition() >= toIndex) &&
(item.getPosition() < fromIndex)) {
item.setPosition(item.getPosition() + 1);
}
}
}
}
podcast.setPosition(toIndex);
sortPodcastList(0, 0);
}
public int getPodcastCount() {
return _podcastItems.size();
}
public Object[] getPodcastList() {
List<Podcast> tmpList = getPodcastListAsList();
Collections.sort(tmpList, new PodcastsComparator(_podcastSortColumn, _podcastSortDirection));
updatePodcastsPosition(tmpList);
return tmpList.toArray(new Podcast[0]);
}
private void sortPodcastList(int column, int direction) {
_podcastSortDirection = direction;
_podcastSortColumn = column;
Controller.getInstance().getEventController().firePlaylistChange(EventConstants.EVT_SORT_PLAYLIST_LIST, null, null);
}
public void sortPodcastList(int column) {
if (column == _podcastSortColumn) {
switch(_podcastSortDirection) {
case 0 : _podcastSortDirection = 1; break;
case 1 : _podcastSortDirection = 0; break;
default : _podcastSortDirection = 0;
}
}
sortPodcastList(column, _podcastSortDirection);
}
public boolean doesPodcastExist(String podcastName) {
if (Util.isWindows()) {
boolean result = false;
Iterator<String> iter = _podcastItems.keySet().iterator();
while ((!result) &&
(iter.hasNext())) {
if (iter.next().equalsIgnoreCase(podcastName)) {
result = true;
}
}
return result;
} else {
return _podcastItems.containsKey(podcastName);
}
}
public void loadPodcasts() {
Log.getInstance(PlaylistController.class).debug("Reading podcasts from: " + SystemUtils.podcastDirectory); //$NON-NLS-1$
File podcastDir = new File(SystemUtils.podcastDirectory);
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return !name.startsWith(".") && name.endsWith(SystemUtils.podcastExtension); //$NON-NLS-1$
}
};
String name;
String[] files = podcastDir.list(filter);
Podcast podcast;
for (int i = 0; i < files.length; i++) {
name = files[i].substring(0, files[i].lastIndexOf(SystemUtils.podcastExtension));
podcast = new Podcast(name, "", "", "");
podcast.loadFromDisk();
_podcastItems.put(name, podcast);
}
}
public void writePodcasts() {
Log.getInstance(PlaylistController.class).debug("Writting podcasts to: " + SystemUtils.podcastDirectory); //$NON-NLS-1$
Podcast item;
Set<String> keys;
Iterator<String> iter;
keys = _podcastItemsToDelete.keySet();
iter = keys.iterator();
while (iter.hasNext()) {
item = _podcastItemsToDelete.get(iter.next());
item.deletePodcast();
}
keys = _podcastItems.keySet();
iter = keys.iterator();
while (iter.hasNext()) {
item = _podcastItems.get(iter.next());
item.writeToDisk();
}
}
/**
* Load the playlists from the playlist directory into the playlist list.
*/
public void loadPlaylists() {
Log.getInstance(PlaylistController.class).debug("Reading playlists from : " + SystemUtils.playlistDirectory); //$NON-NLS-1$
importOldPlaylists();
File playlistDir = new File(SystemUtils.playlistDirectory);
FilenameFilter filter = new FilenameFilter() {
public boolean accept(File dir, String name) {
return !name.startsWith(".") && name.endsWith(SystemUtils.playlistXSPFExtension); //$NON-NLS-1$
}
};
String name;
String[] files = playlistDir.list(filter);
for (int i = 0; i < files.length; i++) {
name = files[i].substring(0, files[i].lastIndexOf(SystemUtils.playlistXSPFExtension));
addPlaylist(name, SystemUtils.playlistDirectory + files[i]);
}
}
/**
* Write the playlist list to the playlist directory.
* First delete the removed playlists.
*/
public void writePlaylists() {
Log.getInstance(PlaylistController.class).debug("Writting playlists to : " + SystemUtils.playlistDirectory); //$NON-NLS-1$
Playlist item;
Set<String> keys;
Iterator<String> iter;
keys = _itemsToDelete.keySet();
iter = keys.iterator();
while (iter.hasNext()) {
item = _itemsToDelete.get(iter.next());
item.deletePlaylist();
}
keys = _items.keySet();
iter = keys.iterator();
while (iter.hasNext()) {
item = _items.get(iter.next());
item.writePlaylist();
}
}
public int getPlaylistsCount() {
return _items.size();
}
public IPlaylist getCurrentPlaylist() {
return _currentPlaylist;
}
public IAudioItem getCurrentAudioItem() {
return _currentAudioItem;
}
public void invalidateAllLoadedTags() {
Iterator<String> iter = _items.keySet().iterator();
while (iter.hasNext()) {
_items.get(iter.next()).invalidateAllLoadedTags();
}
Controller.getInstance().getEventController().fireAudioItemChange(EventConstants.EVT_ITEM_CHANGE_IN_PLAYLIST, null, null);
}
public String buildPlaylistNameFromFile(String fileName) {
String name = fileName.substring(fileName.lastIndexOf(SystemUtils.fileSeparator ) + 1, fileName.lastIndexOf(".")); //$NON-NLS-1$
if (doesPlaylistExist(name)) {
int i = 1;
String nameInt = name + i;
while (doesPlaylistExist(nameInt)) {
i++;
nameInt = name + i;
}
name = nameInt;
}
return name;
}
}
/**
* Add the specified artist to the specified playlist.
* Trigger an EVT_ITEM_CHANGE_IN_PLAYLIST event.
* @param playlistName
* @param artistName
* @param playFirst Play the first file after having enqueued artist
public void addArtistToPlaylist(String playlistName, String artistName, boolean playFirst) {
if (_items.containsKey(playlistName)) {
ArtistItem artistItem = Controller.getInstance().getLibrary().getArtistByName(artistName);
if (artistItem != null) {
LibraryArtistAdder adder = new LibraryArtistAdder(playlistName, artistItem);
ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getDefault().getActiveShell());
try {
dialog.run(true, true, adder);
} catch (InvocationTargetException e) {
Log.getInstance(PlaylistController.class).error(e.getMessage());
} catch (InterruptedException e) {
Log.getInstance(PlaylistController.class).error(e.getMessage());
}
if (playFirst) {
//if (artistItem.getChildrenList().size() > 0) {
if (artistItem.getList().size() > 0) {
//AlbumItem albumItem = artistItem.getChildrenList().get(0);
AlbumItem albumItem = (AlbumItem)artistItem.getList().get(0);
//if (albumItem.getChildrenList().size() > 0) {
if (albumItem.getList().size() > 0) {
Playlist playlist = getPlaylistByName(playlistName);
if (playlist != null) {
//AudioItem item = playlist.getAudioItemByPath(albumItem.getChildrenList().get(0).getFilePath());
AudioItem item = playlist.getAudioItemByPath(((TitleItem) albumItem.getList().get(0)).getFilePath());
if (item != null) {
playFile(playlistName, item);
}
}
}
}
}
fireAudioItemChange(Constants.EVT_ITEM_CHANGE_IN_PLAYLIST, null, null);
} else
Log.getInstance(PlaylistController.class).info("Artist not found : " + artistName); //$NON-NLS-1$
} else
Log.getInstance(PlaylistController.class).info("Playlist not found : " + playlistName); //$NON-NLS-1$
}
*/
/**
* Add the specified album of the specified artist to the specified playlist.
* Trigger an EVT_ITEM_CHANGE_IN_PLAYLIST event.
* @param playlistName
* @param artistName
* @param playFirst Play the first file after having enqueued album
public void addAlbumToPlaylist(String playlistName, String artistName, String albumName, boolean playFirst) {
if (_items.containsKey(playlistName)) {
ArtistItem artistItem = Controller.getInstance().getLibrary().getArtistByName(artistName);
if (artistItem != null) {
//AlbumItem albumItem = artistItem.getAlbumByName(albumName);
AlbumItem albumItem = (AlbumItem) artistItem.getLibraryItemByName(albumName);
if (albumItem != null) {
LibraryAlbumAdder adder = new LibraryAlbumAdder(playlistName, albumItem);
ProgressMonitorDialog dialog = new ProgressMonitorDialog(Display.getDefault().getActiveShell());
try {
dialog.run(true, true, adder);
} catch (InvocationTargetException e) {
Log.getInstance(PlaylistController.class).error(e.getMessage());
} catch (InterruptedException e) {
Log.getInstance(PlaylistController.class).error(e.getMessage());
}
if (playFirst) {
//if (albumItem.getChildrenList().size() > 0) {
if (albumItem.getList().size() > 0) {
Playlist playlist = getPlaylistByName(playlistName);
if (playlist != null) {
//AudioItem item = playlist.getAudioItemByPath(albumItem.getChildrenList().get(0).getFilePath());
AudioItem item = playlist.getAudioItemByPath(((TitleItem) albumItem.getList().get(0)).getFilePath());
if (item != null) {
playFile(playlistName, item);
}
}
}
}
fireAudioItemChange(Constants.EVT_ITEM_CHANGE_IN_PLAYLIST, null, null);
} else
Log.getInstance(PlaylistController.class).info("Album not found : " + albumName); //$NON-NLS-1$
} else
Log.getInstance(PlaylistController.class).info("Artist not found : " + artistName); //$NON-NLS-1$
} else
Log.getInstance(PlaylistController.class).info("Playlist not found : " + playlistName); //$NON-NLS-1$
}
*/