/* * File : MediaBag.java * Created : 19-dec-2000 15:49 * By : fbusquets * * JClic - Authoring and playing system for educational activities * * Copyright (C) 2000 - 2005 Francesc Busquets & Departament * d'Educacio de la Generalitat de Catalunya * * 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 * (at your option) 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 (see the LICENSE file). */ package edu.xtec.jclic.bags; import edu.xtec.jclic.PlayStation; import edu.xtec.jclic.edit.Editable; import edu.xtec.jclic.edit.Editor; import edu.xtec.jclic.fileSystem.FileSystem; import edu.xtec.jclic.project.JClicProject; import edu.xtec.jclic.skins.Skin; import edu.xtec.util.Domable; import edu.xtec.util.ExtendedByteArrayInputStream; import edu.xtec.util.FontCheck; import edu.xtec.util.JDomUtility; import edu.xtec.util.StreamIO; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; /** * This class stores and manages all the media components (images, sounds, animations, * video, MIDI files, etc.) needed to run the activities of a * {@link edu.xtec.jclic.project.JClicProject}. The main member of the class is a * {@link java.util.ArrayList} that stores {@link edu.xtec.jclic.bags.MediaBagElement} * objects. It defines also a {@link edu.xtec.jclic.bags.MediaBag.Listener} interface * to allow other objects to be informed about changes in the media collection. * @author Francesc Busquets (fbusquets@xtec.cat) * @version 13.09.10 */ public class MediaBag extends Object implements Editable, Domable, StreamIO.InputStreamProvider { /** * The project this <CODE>MediaBag</CODE> belongs to */ protected JClicProject project; /** * List containing all the {@link edu.xtec.jclic.bags.MediaBagElement} objects of * this <CODE>MediaBag</CODE>. */ protected List<MediaBagElement> elements; protected Set<Listener> listeners; /** Creates new MediaBag */ public MediaBag(JClicProject project) { this.project=project; elements=new ArrayList<MediaBagElement>(30); listeners=new HashSet<Listener>(1); } public JClicProject getProject(){ return project; } public static String ELEMENT_NAME="mediaBag"; /** * Provides a copy of the elements List * @return a List (currently an ArrayList) of the elements */ public List<MediaBagElement> getElements(){ return new ArrayList<MediaBagElement>(elements); } public void clear(){ elements.clear(); } public List<MediaBagElement> getElementsByName(){ List<MediaBagElement> v=getElements(); Collections.sort(v, new Comparator<MediaBagElement>(){ public int compare(MediaBagElement o1, MediaBagElement o2){ return o1.getName().compareToIgnoreCase(o2.getName()); } }); return v; } public List<MediaBagElement> getElementsByType(){ final StringBuilder sb1=new StringBuilder(200); final StringBuilder sb2=new StringBuilder(200); List<MediaBagElement> v=getElements(); Collections.sort(v, new Comparator<MediaBagElement>(){ public int compare(MediaBagElement o1, MediaBagElement o2){ sb1.setLength(0); String fName=o1.getFileName(); String name=o1.getName(); int dot=fName.lastIndexOf('.'); sb1.append(dot>0 ? fName.substring(dot) : ".zzz"); sb1.append(name); sb2.setLength(0); fName=o2.getFileName(); name=o2.getName(); dot=fName.lastIndexOf('.'); sb2.append(dot>0 ? fName.substring(dot) : ".zzz"); sb2.append(name); return sb1.substring(0).compareToIgnoreCase(sb2.substring(0)); } }); return v; } public org.jdom.Element getJDomElement(){ org.jdom.Element e=new org.jdom.Element(ELEMENT_NAME); Iterator<MediaBagElement> it=getElementsByType().iterator(); while(it.hasNext()) e.addContent(it.next().getJDomElement()); return e; } public void clearData(){ Iterator<MediaBagElement> it=elements.iterator(); while(it.hasNext()) it.next().clearData(); } public void setProperties(org.jdom.Element e, Object aux) throws Exception{ JDomUtility.checkName(e, ELEMENT_NAME); Iterator it=e.getChildren(MediaBagElement.ELEMENT_NAME).iterator(); while(it.hasNext()){ elements.add(MediaBagElement.getMediaBagElement((org.jdom.Element)it.next())); } } public boolean addElement(MediaBagElement mbe){ boolean result=mbe!=null && (getElement(mbe.getName())==null); if(result) elements.add(mbe); return result; } public MediaBagElement getElement(String name){ MediaBagElement result=null; if(name!=null){ for(int i=0; i<elements.size(); i++){ MediaBagElement mbe=elements.get(i); if(name.equals(mbe.getName())){ result=mbe; break; } } } return result; } public MediaBagElement getElementByFileName(String fileName){ MediaBagElement result=null; if(fileName!=null){ for(int i=0; i<elements.size(); i++){ MediaBagElement mbe=elements.get(i); if(fileName.equals(mbe.getFileName())){ result=mbe; break; } } } return result; } public MediaBagElement registerElement(String name, String fileName){ MediaBagElement result=getElement(name); if(result==null){ result=new MediaBagElement(FileSystem.stdFn(fileName==null ? name : fileName), null, name); elements.add(result); } return result; } public boolean removeElement(MediaBagElement mbe){ return elements.remove(mbe); } public Object getMediaDataSource(String name) throws Exception{ Object result=null; String normalizedName=project.getFileSystem().getCanonicalNameOf(name); MediaBagElement mbe=registerElement(normalizedName, null); if(mbe!=null){ if(mbe.getData()!=null){ if(mbe.getData() instanceof ExtendedByteArrayInputStream) result=((ExtendedByteArrayInputStream)mbe.getData()).duplicate(); else result=mbe.getData(); } else{ result=project.getFileSystem().getMediaDataSource(mbe.getFileName()); mbe.setData(result); } } return result; } public InputStream getInputStream(String name) throws Exception{ InputStream result=null; String normalizedName=project.getFileSystem().getCanonicalNameOf(name); MediaBagElement mbe=registerElement(normalizedName, null); if(mbe!=null){ if(mbe.getData() instanceof ExtendedByteArrayInputStream){ ExtendedByteArrayInputStream ebais=(ExtendedByteArrayInputStream)mbe.getData(); mbe.setData(ebais); result=(ebais).duplicate(); } else{ result=project.getFileSystem().getInputStream(mbe.getFileName()); if(result instanceof ExtendedByteArrayInputStream) mbe.setData(result); } } return result; } public MediaBagElement getImageElement(String name) throws Exception{ MediaBagElement result; String normalizedName=project.getFileSystem().getCanonicalNameOf(name); result=registerElement(normalizedName, null); if(result!=null) result = result.prepareImage(project.getFileSystem()) ? result : null; return result; } public void buildFonts() { // count currently empty font elements Map<String,MediaBagElement> fonts=new HashMap<String,MediaBagElement>(); Iterator<MediaBagElement> it=elements.iterator(); while(it.hasNext()){ MediaBagElement mbe=it.next(); String name=mbe.getName(); if(name!=null && mbe.getData()==null && mbe.getFileName().endsWith(".ttf")){ fonts.put(name, mbe); } } if(!fonts.isEmpty()){ String[] fontList=FontCheck.getFontList(false); int nFontsList=fontList.length; Iterator<String> itf=fonts.keySet().iterator(); while(itf.hasNext()){ String name=itf.next(); int i=0; for(; i<nFontsList; i++) if(fontList[i].equalsIgnoreCase(name)) break; if(i==nFontsList){ MediaBagElement mbe=fonts.get(name); try{ mbe.setData(FontCheck.buildNewFont(mbe.getFileName(), this, name)); } catch(Exception ex){ System.err.println("Unable to create font:\n"+ex); } } } } } public Skin getSkinElement(String name, PlayStation ps){ if(name.startsWith(Skin.INTERNAL_SKIN_PREFIX)){ try{ return Skin.getSkin(name, project.getFileSystem(), ps); } catch(Exception e){ System.err.println("Error loading skin \"" + name + "\":\n"+e); } } else{ String normalizedName=project.getFileSystem().getCanonicalNameOf(name); MediaBagElement mbe=registerElement(normalizedName, null); if(mbe!=null){ if(mbe.getData()==null || !(mbe.getData() instanceof Skin)){ try{ Skin sk=Skin.getSkin(mbe.getFileName(), project.getFileSystem(), ps); mbe.setData(sk); } catch(Exception e){ System.err.println("Error loading skin \"" + mbe.getFileName() + "\":\n"+e); } } return (Skin)mbe.getData(); } } return null; } public boolean isWaitingForImages(){ Iterator<MediaBagElement> it=elements.iterator(); while(it.hasNext()){ MediaBagElement mbe=it.next(); if(mbe!=null && mbe.isWaitingForImage()) return true; } return false; } public void waitForAllImages(){ while(isWaitingForImages()){ try{ Thread.sleep(100); } catch(Exception ex){ System.err.println("error waiting for images!\n"+ex); return; } } } public Editor getEditor(Editor parent) { return Editor.createEditor(getClass().getName()+"Editor", this, parent); } public interface Listener{ public void listReferences(String type, Map<String, String> map); public void listReferencesTo(String name, String type, Map<String, String> map); } public void addListener(Listener lst){ if(!listeners.contains(lst)) listeners.add(lst); } public void removeListener(Listener lst){ listeners.remove(lst); } public void listReferencesTo(String name, String type, Map<String, String> map){ Iterator<Listener> it=listeners.iterator(); while(it.hasNext()) it.next().listReferencesTo(name, type, map); } }