Documentation project

Discuss issues related to PS3 Media Server development (only for programmers)

Documentation project

Postby el.botijo » Thu Mar 11, 2010 12:49 am

Let me add some comments to the files. I am following Javadoc conventions, so that they show nicely in Eclipse (it does something like javadoc on the fly).

Following text is a patch for version PMS.java version 405.
Code: Select all
Index: net/pms/PMS.java
===================================================================
--- net/pms/PMS.java   (revision 405)
+++ net/pms/PMS.java   (working copy)
@@ -119,19 +119,53 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.notNullValue;
 
+/**
+ * PS3 Media Server, for streaming any medias to your PS3.<br>
+ * Copyright (C) 2008  A.Brochard
+ *<p>
+ * 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; version 2
+ * of the License only.
+ *<p>
+ * 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.
+ *<p>
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ *
+ */
 public class PMS {
    
+   /**
+    * Update URL used in the {@link AutoUpdater}.
+    */
    private static final String UPDATE_SERVER_URL = "http://ps3mediaserver.googlecode.com/svn/trunk/ps3mediaserver/update.data"; //$NON-NLS-1$
+   /**
+    * Version showed in the UPNP XML descriptor and logs.
+    */
    public static final String VERSION = "1.20.404"; //$NON-NLS-1$
    public static final String AVS_SEPARATOR = "\1"; //$NON-NLS-1$
 
    // TODO(tcox):  This shouldn't be static
    private static PmsConfiguration configuration;
 
+   /**Returns a pointer to the main PMS GUI.
+    * @return {@link IFrame} Main PMS window.
+    */
    public IFrame getFrame() {
       return frame;
    }
 
+   /**getRootFolder returns the Root Folder for a given renderer. There could be the case
+    * where a given media renderer needs a different root structure.
+    * @param renderer {@link RendererConfiguration} is the renderer for which to get the RootFolder structure. If <b>null</b>, then
+    * the default renderer is used.
+    * @return {@link RootFolder} The root folder structure for a given renderer
+    */
    public RootFolder getRootFolder(RendererConfiguration renderer) {
       // something to do here for multiple directories views for each renderer
       if (renderer == null)
@@ -139,7 +173,13 @@
       return renderer.getRootFolder();
    }
 
+   /**
+    * Pointer to a running PMS server.
+    */
    private static PMS instance = null;
+   /**
+    * Semaphore used in order to not create two PMS at the same time.
+    */
    private static byte[] lock = null;
    static {
       lock = new byte[0];
@@ -147,8 +187,15 @@
       sdfDate = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.US); //$NON-NLS-1$
    }
    
+   /**
+    * Array of {@link RendererConfiguration} that have been found by PMS.
+    */
    private ArrayList<RendererConfiguration> foundRenderers = new ArrayList<RendererConfiguration>();
    
+   /**Adds a {@link RendererConfiguration} to the list of media renderers found. The list is being used, for
+    * example, to give the user a graphical representation of the found media renderers.
+    * @param mediarenderer {@link RendererConfiguration}
+    */
    public void setRendererfound(RendererConfiguration mediarenderer) {
       if (!foundRenderers.contains(mediarenderer)) {
          foundRenderers.add(mediarenderer);
@@ -165,11 +212,23 @@
    }
    
    //private RootFolder rootFolder;
+   /**
+    * HTTP server that serves the XML files needed by UPNP server and the media files.
+    */
    private HTTPServer server;
+   /**
+    * User friendly name for the server.
+    */
    private String serverName;
    private ArrayList<Format> extensions;
+   /**
+    * List of registered {@link Player}.
+    */
    private ArrayList<Player> players;
    private ArrayList<Player> allPlayers;
+   /**
+    * @return ArrayList of {@link Player}.
+    */
    public ArrayList<Player> getAllPlayers() {
       return allPlayers;
    }
@@ -183,31 +242,63 @@
    public static SimpleDateFormat sdfDate;
    public static SimpleDateFormat sdfHour;
    
+   /** Information level DEBUG. Lowest level.
+    * @see #message(int, String)
+    */
    public static final int DEBUG = 0;
+   /** Information level INFO.
+    * @see #message(int, String)
+    */
    public static final int INFO = 1;
+   /** Information level MINIMAL. Highest level. Messages with this level are always printed to the command line window.
+    * @see #message(int, String)
+    */
    public static final int MINIMAL = 2;
    
    private PrintWriter pw;
    
+   /**
+    * ArrayList of active processes.
+    */
    public ArrayList<Process> currentProcesses = new ArrayList<Process>();
    
    private PMS() {
    }
    
+   /**
+    * {@link IFrame} object that represents PMS GUI.
+    */
    IFrame frame;
    
+   /**
+    * @see Platform#isWindows()
+    */
    public boolean isWindows() {
       return Platform.isWindows();
    }
 
    private int proxy;
    
+   /**Interface to Windows specific functions, like Windows Registry. registry is set by {@link #init()}.
+    * @see WinUtils
+    */
    private WinUtils registry;
    
+   /**
+    * @see WinUtils
+    */
    public WinUtils getRegistry() {
       return registry;
    }
 
+   /**Executes a new Process and creates a fork that waits for its results.
+    * TODO:Extend explanation on where this is being used.
+    * @param name Symbolic name for the process to be launched, only used in the trace log
+    * @param error (boolean) Set to true if you want PMS to add error messages to the trace pane
+    * @param params (array of Strings) array containing the command to call and its arguments
+    * @return Returns true if the command exited as expected
+    * @throws Exception TODO: Check which exceptions to use
+    */
    private boolean checkProcessExistence(String name, boolean error, String...params) throws Exception {
       PMS.info("launching: " + params[0]); //$NON-NLS-1$
       
@@ -253,11 +344,22 @@
       }
    }
    
+   /**
+    * @see System#err
+    */
    @SuppressWarnings("unused")
    private PrintStream stderr = System.err; 
    
+   /**Main resource database that supports search capabilities. Also known as media cache.
+    * @see DLNAMediaDatabase
+    */
    private DLNAMediaDatabase database;
    
+   /**Used to get the database. Needed in the case of the Xbox 360, that requires a database.
+    * for its queries.
+    * @return (DLNAMediaDatabase) If there exists a database register with the program, a pointer to it is returned.
+    * If there is no database in memory, a new one is created. If the option to use a "cache" is deactivated, returns <b>null</b>.
+    */
    public synchronized DLNAMediaDatabase getDatabase() {
       if (PMS.configuration.getUseCache()) {
          if (database == null) {
@@ -277,6 +379,11 @@
    }
    
    
+   /**Initialisation procedure for PMS.
+    * @return true if the server has been init correctly. false if the server could
+    * not be set to listen to the UPNP port.
+    * @throws Exception
+    */
    private boolean init () throws Exception {
       
       
@@ -470,6 +577,18 @@
       return true;
    }
    
+   /**Creates a new Root folder for a given configuration. It adds following folders in this order:
+    * <ol><li>Directory folders as stated in the configuration pane
+    * <li>Web nodes
+    * <li>iPhoto
+    * <li>iTunes
+    * <li>Media Library
+    * <li>Folders created by plugins
+    * <li>Video settings
+    * </ol>
+    * @param renderer {@link RendererConfiguration} to be managed.
+    * @throws IOException
+    */
    public void manageRoot(RendererConfiguration renderer) throws IOException {
       File files [] = loadFoldersConf(configuration.getFolders());
       if (files == null || files.length == 0)
@@ -561,6 +680,11 @@
    }
 
 
+   /**Adds iPhoto folder. Used by manageRoot, so it is usually used as a folder at the
+    * root folder. Only works when PMS is run on MacOsX.
+    * TODO: Requirements for iPhoto.
+    * @param renderer
+    */
    @SuppressWarnings("unchecked")
    public void addiPhotoFolder(RendererConfiguration renderer) {
       if (Platform.isMac()) {
@@ -610,6 +734,14 @@
       }
    }
    
+   /**Returns the iTunes XML file. This file has all the information of the iTunes
+    * database. The methods used in this function depends on whether PMS runs on
+    * MacOsX or Windows.
+    * @param isOsx deprecated and not used
+    * @return (String) Absolute path to the iTunes XML file.
+    * @throws Exception
+    * @see {@link PMS#addiTunesFolder(RendererConfiguration)}
+    */
    @SuppressWarnings("deprecation")
    private String getiTunesFile(boolean isOsx) throws Exception {
       String line = null;
@@ -650,6 +782,15 @@
       return iTunesFile;
    }
    
+   /**Adds iTunes folder. Used by manageRoot, so it is usually used as a folder at the
+    * root folder. Only works when PMS is run on MacOsX or Windows.<p>
+    * The iTunes XML is parsed fully when this method is called, so it can take some time for
+    * larger (+1000 albums) databases. TODO: Check if only music is being added.<P>
+    * This method does not support genius playlists and does not provide a media library.
+    * @param renderer {@link RendererConfiguration} Which media renderer to add this folder to.
+    * @see PMS#manageRoot(RendererConfiguration)
+    * @see PMS#getiTunesFile(boolean)
+    */
    @SuppressWarnings("unchecked")
    public void addiTunesFolder(RendererConfiguration renderer) {
       if (Platform.isMac() || Platform.isWindows()) {
@@ -692,7 +833,12 @@
          }
       }
    }
-   
+   /**Adds Video Settings folder. Used by manageRoot, so it is usually used as a folder at the
+    * root folder. Child objects are created when this folder is created.
+    * @param renderer {@link RendererConfiguration} Which media renderer to add this folder to.
+    * @see PMS#manageRoot(RendererConfiguration)
+    */
+
    public void addVideoSettingssFolder(RendererConfiguration renderer) {
       if (!PMS.configuration.getHideVideoSettings()) {
          VirtualFolder vf = new VirtualFolder(Messages.getString("PMS.37"), null); //$NON-NLS-1$
@@ -787,6 +933,10 @@
       }
    }
    
+   /**Adds as many folders as plugins providing root folders are loaded into memory (need to implement AdditionalFolderAtRoot)
+    * @param renderer {@link RendererConfiguration} Which media renderer to add this folder to.
+    * @see PMS#manageRoot(RendererConfiguration)
+    */
    private void addAdditionalFoldersAtRoot(RendererConfiguration renderer) {
       for(ExternalListener listener:ExternalFactory.getExternalListeners()) {
          if (listener instanceof AdditionalFolderAtRoot)
@@ -797,10 +947,19 @@
    //private boolean mediaLibraryAdded = false;
    private MediaLibrary library;
    
+   /**Returns the MediaLibrary used by PMS.
+    * @return (MediaLibrary) Used library, if any. null if none is in use.
+    */
    public MediaLibrary getLibrary() {
       return library;
    }
 
+   /**Creates a new MediaLibrary object and adds the Media Library folder at root. This function
+    * can only be run once, or the previous MediaLibrary object can be lost.<P>
+    * @param renderer {@link RendererConfiguration} Which media renderer to add this folder to.
+    * @return true if the settings allow to have a MediaLibrary.
+    * @see PMS#manageRoot(RendererConfiguration)
+    */
    public boolean addMediaLibraryFolder(RendererConfiguration renderer) {
       if (PMS.configuration.getUseCache() && !renderer.isMediaLibraryAdded()) {
          library = new MediaLibrary();
@@ -812,6 +971,11 @@
       return false;
    }
    
+   /**Executes the needed commands in order to make PMS a Windows service that starts whenever the machine is started.
+    * This function is called from the Network tab.
+    * @return true if PMS could be installed as a Windows service.
+    * @see NetworkTab#build()
+    */
    public boolean installWin32Service() {
       PMS.minimal(Messages.getString("PMS.41")); //$NON-NLS-1$
       String cmdArray [] = new String[] { "win32/service/wrapper.exe", "-r", "wrapper.conf" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
@@ -825,6 +989,12 @@
       return pwinstall.isSuccess();
    }
    
+   /**Splits an String using the "." character. Assumes that at least a "." character will be found.<P>
+    * Used by {@link PMS#manageRoot(RendererConfiguration)} in the web.conf section.
+    * @param entry (String) to be splitted
+    * @return Array of (String) that represents the splitted entry.
+    * @see PMS#manageRoot(RendererConfiguration)
+    */
    private String [] parseFeedKey(String entry) {
       StringTokenizer st = new StringTokenizer(entry, "."); //$NON-NLS-1$
       String results [] = new String [2];
@@ -835,6 +1005,12 @@
       return results;
    }
    
+   /**Splits an String using the "," character. Assumes that at least a "," character will be found.<P>
+    * Used by {@link PMS#manageRoot(RendererConfiguration)} in the web.conf section.
+    * @param entry (String) to be splitted
+    * @return Array of (String) that represents the splitted entry.
+    * @see PMS#manageRoot(RendererConfiguration)
+    */
    private String [] parseFeedValue(String entry) {
       StringTokenizer st = new StringTokenizer(entry, ","); //$NON-NLS-1$
       String results [] = new String [3];
@@ -845,6 +1021,9 @@
       return results;
    }
    
+   /**Add a known set of extensions to the extensions list.
+    * @see PMS#init()
+    */
    private void registerExtensions() {
       extensions.add(new WEB());
       extensions.add(new MKV());
@@ -862,6 +1041,9 @@
       extensions.add(new RAW());
    }
    
+   /**Register a known set of audio/video transform tools (known as {@link Player}) . Used in PMS#init().
+    * @see PMS#init()
+    */
    private void registerPlayers() {
       assertThat(configuration, notNullValue());
       if (Platform.isWindows())
@@ -884,6 +1066,11 @@
       frame.addEngines();
    }
    
+   /**Adds a single {@link Player} to the list of Players. Used by {@link PMS#registerPlayers()}.
+    * @param p (Player) to be added to the list
+    * @see Player
+    * @see PMS#registerPlayers()
+    */
    private void registerPlayer(Player p) {
       allPlayers.add(p);
       boolean ok = false;
@@ -922,6 +1109,14 @@
       }
    }
    
+   /**Transforms a comma separated list of directory entries into an array of {@link String}.
+    * The function checks that the directory is exists and is a valid directory. It does not check
+    * if you can access to the files inside the given directory.
+    * @param folders {@link String} Comma separated list of directories.
+    * @return {@link File}[] Array of directories.
+    * @throws IOException
+    * @see {@link PMS#manageRoot(RendererConfiguration)}
+    */
    public File [] loadFoldersConf(String folders) throws IOException {
       if (folders == null || folders.length() == 0)
          return null;
@@ -946,6 +1141,10 @@
    }
 
    
+   /**Restarts the servers. The trigger is either a button on the main PMS window or via
+    * an action item added via {@link PMS#addVideoSettingssFolder(RendererConfiguration).
+    * @throws IOException
+    */
    public void reset() throws IOException {
       debug("Waiting 1 seconds..."); //$NON-NLS-1$
       UPNPHelper.sendByeBye();
@@ -964,28 +1163,53 @@
       UPNPHelper.sendAlive();
    }
    
+   /**Adds a message to the debug stream, or {@link System#out} in case the
+    * debug stream has not been set up yet.
+    * @param msg {@link String} to be added to the debug stream.
+    */
    public static void debug(String msg) {
       if (instance != null)
          instance.message(DEBUG, msg);
       else
          System.out.println(msg);
    }
-   
+   /**Adds a message to the info stream.
+    * @param msg {@link String} to be added to the info stream.
+    */
    public static void info(String msg) {
       if (instance != null)
          instance.message(INFO, msg);
    }
    
+   /**Adds a message to the minimal stream. This minimal stream is also
+    * shown in the Trace tab.
+    * @param msg {@link String} to be added to the minimal stream.
+    */
    public static void minimal(String msg) {
       if (instance != null)
          instance.message(MINIMAL, msg);
    }
    
+   /**Adds a message to the error stream. This is usually called by
+    * statements that are in a try/catch block.
+    * @param msg {@link String} to be added to the error stream
+    * @param t {@link Throwable} comes from an {@link Exception}
+    */
    public static void error(String msg, Throwable t) {
       if (instance != null)
          instance.message(msg, t);
    }
    
+   /**Print a message in a given channel. The channels can be following:
+    * <ul><li>{@link #MINIMAL} for informative messages that the user need to be aware of. They are always
+    * submitted to {@link System#out}, so they are shown to the command line window if one exists.
+    * <li>{@link #INFO} for informative messages.
+    * <li>{@link #DEBUG} for debug messages
+    * </ul>
+    * The debug level setting will state which ones of the three levels are being shown.
+    * @param l {@link int} is the output text channel to use.
+    * @param message {@link String} is the message to output
+    */
    private void message(int l, String message) {
       
          String name = Thread.currentThread().getName();
@@ -1014,6 +1238,10 @@
       
    }
    
+   /**Handles the display of an error message. It is always logged and is shown in the command line window if available.
+    * @param error {@link String} to be displayed
+    * @param t {@link Throwable} from the {@link Exception} that has the error description.
+    */
    private void message(String error, Throwable t) {
       
          String name = Thread.currentThread().getName();
@@ -1042,8 +1270,15 @@
       
    }
 
+   /**Universally Unique Identifier used in the UPNP server.
+    *
+    */
    private String uuid;
    
+   /**Creates a new {@link #uuid} for the UPNP server to use. Tries to follow the RCFs for creating the UUID based on the link MAC address.
+    * Defaults to a random one if that method is not available.
+    * @return {@link String} with an Universally Unique Identifier.
+    */
    public String usn() {
       if (uuid == null) {
          boolean uuidBasedOnMAC = false;
@@ -1082,6 +1317,9 @@
       //return "uuid:1234567890TOTO::";
    }
    
+   /**Returns the user friendly name of the UPNP server.
+    * @return {@link String} with the user friendly name.
+    */
    public String getServerName() {
       if (serverName == null) {
          StringBuffer sb = new StringBuffer();
@@ -1097,6 +1335,9 @@
    }
    
    
+   /**Returns the PMS instance. New instance is created if needed.
+    * @return {@link PMS}
+    */
    public static PMS get() {
       if (instance == null) {
          synchronized (lock) {
@@ -1116,6 +1357,10 @@
       return instance;
    }
    
+   /**
+    * @param filename
+    * @return
+    */
    public Format getAssociatedExtension(String filename) {
       PMS.debug("Search extension for " + filename); //$NON-NLS-1$
       for(Format ext:extensions) {

Regards.
el.botijo
 
Posts: 50
Joined: Thu Feb 04, 2010 9:14 pm

Re: Documentation project

Postby el.botijo » Sun Mar 14, 2010 3:54 pm

Second file for documentation.

Code: Select all
Index: net/pms/Messages.java
===================================================================
--- net/pms/Messages.java   (revision 405)
+++ net/pms/Messages.java   (working copy)
@@ -3,6 +3,9 @@
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
 
+/**Class Messages provides a mechanism to localise the text messages found in PMS. It is based
+ * on {@link ResourceBundle}.
+ */
 public class Messages {
    private static final String BUNDLE_NAME = "net.pms.messages"; //$NON-NLS-1$
 
@@ -11,6 +14,12 @@
    private Messages() {
    }
 
+   /**Returns the locale-specific string associated with the key.
+    * @param key Keys in PMS follow the format "group.x". group states where this key is likely to be
+    * used. For example, NetworkTab refers to the network configuration tab in the PMS GUI. x is just
+    * a number.
+    * @return Descriptive string if key is found or a copy of the key string if it is not.
+    */
    public static String getString(String key) {
       try {
          return RESOURCE_BUNDLE.getString(key);
el.botijo
 
Posts: 50
Joined: Thu Feb 04, 2010 9:14 pm

Re: Documentation project

Postby shagrath » Sun Mar 14, 2010 9:06 pm

Thanks for the work :p
shagrath
Project Lead
 
Posts: 2667
Joined: Wed Jan 14, 2009 1:39 pm

Re: Documentation project

Postby Redlum » Mon Mar 15, 2010 11:11 am

Awesome :)
Redlum
Project Member
 
Posts: 371
Joined: Mon Jan 12, 2009 9:13 pm

Re: Documentation project

Postby el.botijo » Sun Mar 21, 2010 7:16 pm

Another two fairly used files: DLNAResource and HTTPResource.
Be aware that I am no developer myself, so I tried my best to add comments here. I might revisit these files whenever I finish with the rest (if I do...). If anybody knows better, please fix the comments with more accurate ones.
Code: Select all
Index: net/pms/dlna/DLNAResource.java
===================================================================
--- net/pms/dlna/DLNAResource.java   (revision 405)
+++ net/pms/dlna/DLNAResource.java   (working copy)
@@ -54,25 +54,59 @@
 import net.pms.util.Iso639;
 import net.pms.util.MpegUtil;
 
+/**
+ * Represents any item that can be browsed via the UPNP ContentDirectory service.
+ *
+ */
 public abstract class DLNAResource extends HTTPResource implements Cloneable {
    
    protected static final int MAX_ARCHIVE_ENTRY_SIZE = 10000000;
    protected static final int MAX_ARCHIVE_SIZE_SEEK = 800000000;
    protected static String TRANSCODE_FOLDER = "#--TRANSCODE--#";
    
+   /**Returns parent object, usually a folder type of resource.
+    * @return Parent object.
+    * @see #parent
+    */
    public DLNAResource getParent() {
       return parent;
    }
    protected int specificType;
+   /**
+    * String representing this resource ID. This string is used by the UPNP ContentDirectory service.
+    * There is no hard spec on the actual numbering except for the root container that always has to be "0".
+    * In PMS, the format used is <i>number($number)+</i>. A common client that expects a given format,
+    * that is different that the one used here, is the XBox360. For more info, check
+    * {@link http://www.mperfect.net/whsUpnp360/} . PMS translates the XBox360 queries on the fly.
+    */
    protected String id;
+   /**
+    * @return ID string
+    * @see #id
+    */
    public String getId() {
       return id;
    }
+   /**
+    * List of children objects associated with this DLNAResource. This is only valid when the DLNAResource is of the container type.
+    */
    protected ArrayList<DLNAResource> children;
+   /**
+    * @return List of children objects
+    * @see #children
+    */
    public ArrayList<DLNAResource> getChildren() {
       return children;
    }
+   /**
+    * In the DLDI queries, the UPNP server needs to give out the parent container where the item is. <i>parent</i> represents
+    * such a container.
+    */
    protected DLNAResource parent;
+   /**
+    * @param parent Sets the parent folder.
+    * @see #parent
+    */
    public void setParent(DLNAResource parent) {
       this.parent = parent;
    }
@@ -89,11 +123,18 @@
       return lastmodified;
    }
 
+   /**
+    * Represents the transformation to be used to the file. If null, then
+    * @see Player
+    */
    protected Player player;
    //protected DLNAResource original;
    public Format getExt() {
       return ext;
    }
+   /**Any {@link DLNAResource} needs to represent the container or item with a String.
+    * @return String to be showed in the UPNP client.
+    */
    public abstract String getName();
    public abstract String getSystemName();
    public abstract long length();
@@ -153,6 +194,14 @@
       this.specificType = specificType;
    }
    
+   /** Recursive function that searchs through all of the children until it finds
+    * a {@link DLNAResource} that matches the name.<p> Only used by {@link PMS#manageRoot(RendererConfiguration)}
+    * while parsing the web.conf file.
+    * @param name String to be compared the name to.
+    * @return Returns a {@link DLNAResource} whose name matches the parameter name
+    * @see #getName()
+    * @see PMS#manageRoot(RendererConfiguration)
+    */
    public DLNAResource searchByName(String name) {
       for(DLNAResource child:children) {
          if (child.getName().equals(name))
@@ -161,6 +210,11 @@
       return null;
    }
    
+   /**
+    * @param renderer Renderer for which to check if file is supported.
+    * @return true if the given {@see RendererConfiguration} can understand type of media. Returns also true
+    * if this DLNAResource is a container.
+    */
    public boolean isCompatible(RendererConfiguration renderer) {
       return ext == null
          || ext.isUnknown()
@@ -172,6 +226,13 @@
    public boolean skipTranscode = false;
    protected int childrenNumber;
    
+   /**Adds a new DLNAResource to the child list. Only useful if this object is of the container type.<P>
+    * TODO: (botijo) check what happens with the child object. This function can and will transform the child
+    * object. If the transcode option is set, the child item is converted to a container with the real
+    * item and the transcode option folder. There is also a parser in order to get the right name and type,
+    * I suppose. Is this the right place to be doing things like these?
+    * @param child DLNAResource to add to a container type.
+    */
    public void addChild(DLNAResource child) {
       //child.expert = expert;
       child.parent = this;
@@ -314,6 +375,14 @@
       }
    }
    
+   /**Recursive function that assigns proper IDs to the items. It follows the format number($number)+.
+    * It is used after all the root directories have been set.
+    * @param index Index where to start numbering.
+    * @param refresh If true, then the IDs are not reset to zero for each child item.
+    * @see #id
+    * @see #children
+    * @see PMS#manageRoot(RendererConfiguration)
+    */
    public synchronized void closeChildren(int index, boolean refresh) {
       if (id == null || id.equals("0")) {
          if (parent != null) {
@@ -329,6 +398,19 @@
          }
    }
    
+   /**First thing it does it searches for an item matching the given objectID.
+    * If children is false, then it returns the found object as the only object in the list.
+    * If item or children have not been discovered already, then the {@link #closeChildren(int, boolean)} is called.<p>
+    * TODO: (botijo) This function does a lot more than this!
+    * @param objectId ID to search for.
+    * @param children State if you want all the children in the returned list.
+    * @param start
+    * @param count
+    * @param renderer Renderer for which to do the actions.
+    * @return List of DLNAResource items.
+    * @throws IOException
+    * @see #closeChildren(int, boolean)
+    */
    public synchronized ArrayList<DLNAResource> getDLNAResources(String objectId, boolean children, int start, int count, RendererConfiguration renderer) throws IOException {
       PMS.debug("Searching for objectId: " + objectId + " with children option: " +children);
       ArrayList<DLNAResource> resources = new ArrayList<DLNAResource>();
@@ -413,6 +495,12 @@
       return resources;
    }
    
+   /**Recursive function that searches for a given ID.
+    * @param searchId ID to search for.
+    * @return Item found, or null otherwise.
+    * @see #id
+    *
+    */
    public DLNAResource search(String searchId) {
       DLNAResource found = null;
       if (id != null) {
@@ -429,14 +517,25 @@
       return found;
    }
    
+   /**
+    * TODO: (botijo) What is the intention of this function? Looks like a prototype to be overloaded.
+    */
    public void discoverChildren() {
       
    }
-   
+   /**
+    * TODO: (botijo) What is the intention of this function? Looks like a prototype to be overloaded.
+    * @param count
+    * @return
+    */
    public boolean analyzeChildren(int count) {
       return true;
    }
    
+   /**
+    * TODO: (botijo) What is the intention of this function? Looks like a prototype to be overloaded.
+    * @return
+    */
    public boolean refreshChildren() {
       return false;
    }
@@ -450,20 +549,35 @@
       }
    }
    
+   /**
+    * TODO: (botijo) What is the intention of this function? Looks like a prototype to be overloaded.
+    *
+    */
    public void resolve() {
       
    }
    
+   /**Appends "&lt;<u>tag</u> " to the StringBuffer. This is a typical HTML/DIDL/XML tag opening.
+    * @param sb String to append the tag beginning to.
+    * @param tag String that represents the tag
+    */
    private void openTag(StringBuffer sb, String tag) {
       sb.append("&lt;");
       sb.append(tag);
       sb.append(" ");
    }
    
+   /**Appends the closing symbol &gt; to the StringBuffer. This is a typical HTML/DIDL/XML tag closing.
+    * @param sb String to append the ending character of a tag.
+    */
    private void endTag(StringBuffer sb) {
       sb.append("&gt;");
    }
    
+   /**Appends "&lt;/<u>tag</u>&gt;" to the StringBuffer. This is a typical closing HTML/DIDL/XML tag.
+    * @param sb
+    * @param tag
+    */
    private void closeTag(StringBuffer sb, String tag) {
       sb.append("&lt;/");
       sb.append(tag);
@@ -488,6 +602,10 @@
    }
    
    // Ditlew
+   /**Returns the DisplayName for the default renderer.
+    * @return
+    * @see #getDisplayName(RendererConfiguration)
+    */
    public String getDisplayName() {
       return getDisplayName(null);
    }
@@ -495,6 +613,12 @@
    // Ditlew - org
    //public String getDisplayName() {
    // Ditlew
+   /**Returns the DisplayName that is shown to the Renderer. Depending on the settings,
+    * extra info might be appended, like item duration.<p>
+    * This is based on {@link #getName()}.
+    * @param mediaRenderer Media Renderer for which to show information.
+    * @return String representing the item.
+    */
    public String getDisplayName(RendererConfiguration mediaRenderer) {
       String name = getName();
       if (this instanceof RealFile) {
@@ -542,10 +666,17 @@
       return name;
    }
    
+   /**Prototype for returning URLs.
+    * @return
+    */
    protected String getFileURL() {
       return getURL("");
    }
    
+   /**
+    * @return Returns an URL pointing to a image representing the item. It none is available, "thumbnail0000.png" is used.
+    * The idea is to use is in the UPNP ContentBrowser service.
+    */
    protected String getThumbnailURL() {
       StringBuffer sb = new StringBuffer();
       sb.append(PMS.get().getServer().getURL());
@@ -569,6 +700,10 @@
       return getURL("thumbnail0000");
    }
    
+   /**
+    * @param prefix
+    * @return Returns an URL for a given media item. Not used for container types.
+    */
    protected String getURL(String prefix) {
       StringBuffer sb = new StringBuffer();
       sb.append(PMS.get().getServer().getURL());
@@ -580,6 +715,10 @@
       return sb.toString();
    }
 
+   /**Transforms a String to UTF-8.
+    * @param s
+    * @return Transformed string s in UTF-8 encoding.
+    */
    private static String encode(String s) {
       try {
          return URLEncoder.encode(s, "UTF-8");
@@ -588,6 +727,14 @@
       return "";
    }
    
+   /**Removes any children associated to this DLNAResource.<p>Note: (botijo) this function is not called anywhere.
+    *
+    * @param level This integer represents how deep the items are in the tree. For the root
+    * container (level==0), you do want to keep the children. For the rest of the levels,
+    * children is set to null.
+    * @see #children
+    */
+//   @Deprecated
    public void reset(int level) {
       for(DLNAResource r:children) {
          r.reset(level++);
@@ -598,11 +745,18 @@
          children = null;
    }
    
+   /**
+    * @return Number of children objects. This might be used in the DLDI response, as some renderers might
+    * not have enough memory to hold the list for every children.
+    */
    public int childrenNumber() {
       if (children == null)
          return 0;
       return children.size();
    }
+   /* (non-Javadoc)
+    * @see java.lang.Object#clone()
+    */
    @Override
    protected Object clone() {
       Object o = null;
@@ -614,6 +768,10 @@
       return o;
    }
    
+   /**Does basic transformations between characters and their HTML representation with ampersands.
+    * @param s String to be encoded
+    * @return Encoded String
+    */
    private String encodeXML(String s) {
       
       s = s.replace("&", "&amp;");
@@ -631,6 +789,11 @@
    public String getFlags() {
       return flags;
    }
+   /**Returns a representation using DIDL response lines. It gives a complete representation of the item, with as many tags as available.
+    * Recommendations as per UPNP specification are followed where possible.
+    * @param mediaRenderer Media Renderer for which to represent this information. Useful for some hacks.
+    * @return String representing the item. An example would start like this: {@code <container id="0$1" childCount=1 parentID="0" restricted="true">}
+    */
    public String toString(RendererConfiguration mediaRenderer) {
       StringBuffer sb = new StringBuffer();
       if (isFolder())
@@ -874,6 +1037,10 @@
       return sb.toString();
    }
    
+   /**
+    * Plugin implementation. When this item is going to play, it will notify all the StartStopListener objects available.
+    * @see StartStopListener
+    */
    public void startPlaying() {
       for(ExternalListener listener:ExternalFactory.getExternalListeners()) {
          if (listener instanceof StartStopListener)
@@ -881,6 +1048,10 @@
       }
    }
    
+   /**
+    * Plugin implementation. When this item is going to play, it will notify all the StartStopListener objects available.
+    * @see StartStopListener
+    */
    public void stopPlaying() {
       for(ExternalListener listener:ExternalFactory.getExternalListeners()) {
          if (listener instanceof StartStopListener)
@@ -888,6 +1059,14 @@
       }
    }
    
+   /**Returns an InputStream of this DLNAResource that starts at a given time, if possible. Very useful if video chapters are being used.
+    * @param low
+    * @param high
+    * @param timeseek
+    * @param mediarenderer
+    * @return
+    * @throws IOException
+    */
    public InputStream getInputStream(long low, long high, double timeseek, RendererConfiguration mediarenderer) throws IOException {
             
       PMS.debug( "Asked stream chunk [" + low + "-" + high + "] timeseek: " + timeseek + " of " + getName() + " and player " + player);
@@ -1032,10 +1211,16 @@
          return getDefaultMimeType(specificType);
    }
    
+   /**
+    * Prototype function. Original comment: need to override if some thumbnail works are to be done when mediaparserv2 enabled
+    */
    public void checkThumbnail() {
       // need to override if some thumbnail works are to be done when mediaparserv2 enabled
    }
    
+   /**Checks if a thumbnail exists, and if possible, generates one.
+    * @param input InputFile to check or generate the thumbnail that is being asked for.
+    */
    protected void checkThumbnail(InputFile input) {
       if (media != null && !media.thumbready && PMS.getConfiguration().getThumbnailsEnabled()) {
          media.thumbready = true;
@@ -1046,6 +1231,10 @@
       }
    }
    
+   /**TODO: (botijo) Prototype function?
+    * @return
+    * @throws IOException
+    */
    public InputStream getThumbnailInputStream() throws IOException {
       /*if (specificType == 0)
          return getResourceInputStream("images/clapperboard-256x256.png");*/
@@ -1061,6 +1250,10 @@
       else
          return Format.UNKNOWN;
    }
+   /**Prototype function.
+    * @return true if child can be added to other folder.
+    * @see #addChild(DLNAResource)
+    */
    public abstract boolean isValid();
    
 }
Index: net/pms/network/HTTPResource.java
===================================================================
--- net/pms/network/HTTPResource.java   (revision 405)
+++ net/pms/network/HTTPResource.java   (working copy)
@@ -32,6 +32,11 @@
 import net.pms.configuration.RendererConfiguration;
 import net.pms.formats.Format;
 
+/**
+ * Implements any item that can be transfered through the HTTP pipes.
+ * In the PMS case, this item represent media files.
+ * @see DLNAResource
+ */
 public class HTTPResource {
    
    public static final String UNKNOWN_VIDEO_TYPEMIME = "video/mpeg";
@@ -68,6 +73,11 @@
       
    }
    
+   /**Returns for a given item type the default MIME type associated. This is used in the HTTP transfers
+    * as in the client might do different things for different MIME types.
+    * @param type Type for which the default MIME type is needed.
+    * @return Default MIME associated with the file type.
+    */
    public String getDefaultMimeType(int type) {
       String mimeType = HTTPResource.UNKNOWN_VIDEO_TYPEMIME;
       if (type == Format.VIDEO)
@@ -80,6 +90,10 @@
    }
    
    
+   /**Returns a InputStream associated to the fileName.
+    * @param fileName TODO Absolute or relative file path.
+    * @return If found, an InputStream associated to the fileName. null otherwise.
+    */
    protected InputStream getResourceInputStream(String fileName) {
       fileName = "/resources/" + fileName;
       ClassLoader cll = this.getClass().getClassLoader();
@@ -91,6 +105,14 @@
       return is;
    }
    
+   /**Creates an InputStream based on an URL. This is used while accessing external resources
+    * like online radios.
+    * @param u URL.
+    * @param saveOnDisk If true, the file is first downloaded in the harddisk in the temporary folder.
+    * @return InputStream that can be used for sending to the UPNP Media Renderer.
+    * @throws IOException
+    * @see downloadAndSendBinary
+    */
    protected InputStream downloadAndSend(String u, boolean saveOnDisk) throws IOException {
       URL url = new URL(u);
       File f = null;
@@ -109,10 +131,23 @@
       return new ByteArrayInputStream(content);
    }
    
+   /**Overloaded method for {@link #downloadAndSendBinary(String, boolean, File)}, without storing any file in the harddisk.
+    * @param u URL to retrieve.
+    * @return byte array.
+    * @throws IOException
+    */
    protected byte [] downloadAndSendBinary(String u) throws IOException {
       return downloadAndSendBinary(u, false, null);
    }
    
+   /**Returns a byte array representation of a file given by an URL. File is downloaded and optionally stored in the harddisk.
+    * @param u URL to retrieve.
+    * @param saveOnDisk If true, store the file in the harddisk.
+    * @param f If saveOnDisk is true, then store the contents of the file represented by u into the associated File. f needs to be opened before
+    * calling this function.
+    * @return
+    * @throws IOException
+    */
    protected byte [] downloadAndSendBinary(String u, boolean saveOnDisk, File f) throws IOException {
       URL url = new URL(u);
       PMS.info("Retrieving " + url.toString());
@@ -137,6 +172,10 @@
       return bytes.toByteArray();
    }
    
+   /**Converts an URL string to it more canonical form
+    * @param url String to be converted
+    * @return Converted String.
+    */
    protected String convertURLToFileName(String url) {
       url = url.replace('/', '\u00b5');
       url = url.replace('\\', '\u00b5');
@@ -149,6 +188,11 @@
       return url;
    }
    
+   /**Returns an associated MIME type related to the Media Renderer. Some Media Renderer might need that the MIME type is not the correct one.
+    * @param mimetype MIME type to transform.
+    * @param mediarenderer Specific Media Renderer.
+    * @return
+    */
    public String getRendererMimeType(String mimetype, RendererConfiguration mediarenderer) {
 //      if (mimetype != null && mimetype.equals(AVI_TYPEMIME)) {
 //         if (mediarenderer == PS3) {
el.botijo
 
Posts: 50
Joined: Thu Feb 04, 2010 9:14 pm

Re: Documentation project

Postby el.botijo » Sun Mar 21, 2010 7:36 pm

Next file.
Code: Select all
Index: net/pms/dlna/virtual/VirtualFolder.java
===================================================================
--- net/pms/dlna/virtual/VirtualFolder.java   (revision 405)
+++ net/pms/dlna/virtual/VirtualFolder.java   (working copy)
@@ -24,12 +24,22 @@
 import net.pms.dlna.DLNAResource;
 import net.pms.network.HTTPResource;
 
+/**
+ * Represents a container (folder). This is widely used by the UPNP ContentBrowser service. Child objects are expected in this folder.
+ */
 public class VirtualFolder extends DLNAResource {
    
    protected String name;
    protected String thumbnailIcon;
    protected String thumbnailContentType;
    
+   /**Constructor for this class. The constructor does not add any child to the container. This is the only
+    * chance to set the name of this container.
+    * @param name String to be shown in the ContentBrowser service
+    * @param thumbnailIcon Represents a thumbnail to be shown. The String represents an absolute
+    *        path. Use null if none is available or desired.
+    * @see #addChild(DLNAResource)
+    */
    public VirtualFolder(String name, String thumbnailIcon) {
       this.name = name;
       this.thumbnailIcon = thumbnailIcon;
@@ -39,26 +49,45 @@
          thumbnailContentType = HTTPResource.JPEG_TYPEMIME;
    }
 
+   /**Because a container cannot be streamed, this function always returns null.
+    * @return null
+    * @see net.pms.dlna.DLNAResource#getInputStream()
+    */
    @Override
    public InputStream getInputStream() throws IOException {
       return null;
    }
 
+   /**Returns a string representing the container. This string is used in
+    * the UPNP ContentBrowser service.
+    * @see net.pms.dlna.DLNAResource#getName()
+    */
    @Override
    public String getName() {
       return name;
    }
 
+   /**Returns true in this case, as this is a folder.
+    * @return true
+    * @see net.pms.dlna.DLNAResource#isFolder()
+    */
    @Override
    public boolean isFolder() {
       return true;
    }
 
+   /**Returns zero as this is a folder (container).
+    * @see net.pms.dlna.DLNAResource#length()
+    */
    @Override
    public long length() {
       return 0;
    }
 
+   /**Containers are likely not to be modified, so this one returns zero.
+    * TODO: (botijo) When is this used then? Is this a prototype?
+    * @return Zero
+    */
    public long lastModified() {
       return 0;
    }
@@ -68,16 +97,26 @@
       return getName();
    }
    
+   /**Returns a {@link InputStream} that represents the thumbnail used.
+    * @see net.pms.dlna.DLNAResource#getThumbnailInputStream()
+    */
    @Override
    public InputStream getThumbnailInputStream() {
       return getResourceInputStream(thumbnailIcon);
    }
    
+   /**Returns the thumbnailContentType associated to the thumbnail associated to this container.
+    * @see net.pms.dlna.DLNAResource#getThumbnailContentType()
+    * @see #thumbnailContentType
+    */
    @Override
    public String getThumbnailContentType() {
       return thumbnailContentType;
    }
 
+   /**Returns true, as a container is always a valid item to add to another container.
+    * @see net.pms.dlna.DLNAResource#isValid()
+    */
    @Override
    public boolean isValid() {
       return true;
el.botijo
 
Posts: 50
Joined: Thu Feb 04, 2010 9:14 pm

Re: Documentation project

Postby el.botijo » Sun Mar 21, 2010 8:13 pm

Code: Select all
Index: net/pms/dlna/virtual/VirtualVideoAction.java
===================================================================
--- net/pms/dlna/virtual/VirtualVideoAction.java   (revision 405)
+++ net/pms/dlna/virtual/VirtualVideoAction.java   (working copy)
@@ -21,10 +21,18 @@
 import java.io.IOException;
 import java.io.InputStream;
 
+import net.pms.Messages;
 import net.pms.PMS;
 import net.pms.dlna.DLNAResource;
 import net.pms.network.HTTPResource;
 
+/**
+ * Implements a container that when browsed, an action will be performed.
+ * The class assumes that the action to be performed is to toggle a boolean value.
+ * Because of this, the thumbnail is either a green tick mark or a red cross. Equivalent
+ * videos are shown after the value is toggled.<p>
+ * However this is just cosmetic. Any action can be performed.
+ */
 public abstract class VirtualVideoAction extends DLNAResource {
    
    private boolean enabled;
@@ -38,6 +46,11 @@
    private long timer1;
    
    
+   /**Constructor for this class. Recommended instantation includes overriding the {@link #enable()} function (example shown in the link).
+    * @param name Name that is shown via the UPNP ContentBrowser service. This field cannot be changed after the instantiation.
+    * @param enabled If true, a green tick mark is shown as thumbnail. If false, a red cross is shown. This initial value
+    * is usually changed via the {@link #enable()} function.
+    */
    public VirtualVideoAction(String name, boolean enabled) {
       this.name = name;
       thumbnailContentType = HTTPResource.PNG_TYPEMIME;
@@ -50,6 +63,14 @@
       this.enabled = enabled;
    }
 
+   /**This function is called as an action from the UPNP client when
+    * the user tries to play this item. This function calls instead the enable()
+    * function in order to execute an action.
+    * As the client expects to play an item, a really short video (less than 1s) is shown with
+    * the results of the action.
+    * @see #enable()
+    * @see net.pms.dlna.DLNAResource#getInputStream()
+    */
    @Override
    public InputStream getInputStream() throws IOException {
       if (timer1 == -1)
@@ -62,6 +83,21 @@
       return getResourceInputStream(enabled?videoOk:videoKo);
    }
    
+   /**Prototype. This function is called by {@link #getInputStream()} and is the core of this class.
+    * The main purpose of this function is toggle a boolean variable somewhere.
+    * The value of that boolean variable is shown then as either a green tick mark or a red cross.
+    * However, this is just a cosmetic thing. Any Java code can be executed in this function, not only toggling a boolean variable.
+    * Recommended way to instantiate this class is as follows (taken from {@link PMS#addVideoSettingssFolder(net.pms.configuration.RendererConfiguration)}:
+    * <pre> VirtualFolder vf;
+    * [...]
+    * vf.addChild(new VirtualVideoAction(Messages.getString("PMS.3"), configuration.isMencoderNoOutOfSync()) { //$NON-NLS-1$
+    *   public boolean enable() {
+    *   configuration.setMencoderNoOutOfSync(!configuration.isMencoderNoOutOfSync());
+    *   return configuration.isMencoderNoOutOfSync();
+    *   }
+    * }); </pre>
+    * @return If true, a green tick mark is shown as thumbnail. If false, a red cross is shown.
+    */
    public abstract boolean enable();
 
    @Override
@@ -69,11 +105,20 @@
       return name;
    }
 
+   /**As this item is not a container, returns false.
+    * @return false
+    * @see net.pms.dlna.DLNAResource#isFolder()
+    */
    @Override
    public boolean isFolder() {
       return false;
    }
 
+   /**Returns an invalid length as this item is not
+    * TODO: (botijo) VirtualFolder returns 0 instead of -1.
+    * @return -1, an invalid length for an item.
+    * @see net.pms.dlna.DLNAResource#length()
+    */
    @Override
    public long length() {
       return -1; //DLNAMediaInfo.TRANS_SIZE;
@@ -88,16 +133,28 @@
       return getName();
    }
    
+   /**Returns either a green tick mark or a red cross that represents the actual
+    * value of this item
+    * @see net.pms.dlna.DLNAResource#getThumbnailInputStream()
+    */
    @Override
    public InputStream getThumbnailInputStream() {
       return getResourceInputStream(enabled?thumbnailIconOK:thumbnailIconKO);
    }
    
+   /**@return PNG type, as the thumbnail can only be either a green tick mark or a red cross.
+    * @see #getThumbnailInputStream()
+    * @see net.pms.dlna.DLNAResource#getThumbnailContentType()
+    */
    @Override
    public String getThumbnailContentType() {
       return thumbnailContentType;
    }
 
+   /**TODO: (botijo) Why is ext being set here?
+    * @return True, as this kind of item is always valid.
+    * @see net.pms.dlna.DLNAResource#isValid()
+    */
    @Override
    public boolean isValid() {
       ext = PMS.get().getAssociatedExtension("toto.mpg");
el.botijo
 
Posts: 50
Joined: Thu Feb 04, 2010 9:14 pm

Re: Documentation project

Postby chocolateboy » Sun Jan 16, 2011 6:44 am

Applied in r433.
chocolateboy
Project Member
 
Posts: 2580
Joined: Wed Sep 16, 2009 10:05 am


Return to Developers

Who is online

Users browsing this forum: No registered users and 6 guests