001    /*
002     * 
003     * $Revision: 15022 $ $Date: 2009-03-26 14:53:00 +0100 (Thu, 26 Mar 2009) $
004     *
005     * This file is part of ***  M y C o R e  ***
006     * See http://www.mycore.de/ for details.
007     *
008     * This program is free software; you can use it, redistribute it
009     * and / or modify it under the terms of the GNU General Public License
010     * (GPL) as published by the Free Software Foundation; either version 2
011     * of the License or (at your option) any later version.
012     *
013     * This program is distributed in the hope that it will be useful, but
014     * WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program, in a file called gpl.txt or license.txt.
020     * If not, write to the Free Software Foundation Inc.,
021     * 59 Temple Place - Suite 330, Boston, MA  02111-1307 USA
022     */
023    
024    package org.mycore.backend.realhelix;
025    
026    import java.io.IOException;
027    import java.io.OutputStream;
028    import java.net.URLConnection;
029    import java.util.StringTokenizer;
030    
031    import org.apache.log4j.Logger;
032    import org.mycore.common.MCRConfiguration;
033    import org.mycore.common.MCRPersistenceException;
034    import org.mycore.datamodel.ifs.MCRAudioVideoExtender;
035    import org.mycore.datamodel.ifs.MCRFileReader;
036    
037    /**
038     * This class implements the AudioVideoExtender functions for Real Server 8 and
039     * Helix Universal Streaming Server 9 instances. It reads technical metadata
040     * about stored assets by parsing the Real Server's "View Source" responses and
041     * gets a player starter file using the "/ramgen/" mount point. The parameters
042     * can be configured in mycore.properties:
043     * 
044     * <code>
045     *   MCR.IFS.AVExtender.<StoreID>.RamGenBaseURL      URL of ramgen mount point
046     *   MCR.IFS.AVExtender.<StoreID>.AsxGenBaseURL      URL of asxgen mount point
047     *   MCR.IFS.AVExtender.<StoreID>.ViewSourceBaseURL  URL of view source function
048     *   MCR.IFS.AVExtender.<StoreID>.RealPlayerURL      Download URL for RealOne Player
049     *   MCR.IFS.AVExtender.<StoreID>.MediaPlayerURL     Download URL for Microsoft Player
050     * </code>
051     * 
052     * @author Frank Lützenkirchen
053     * @version $Revision: 15022 $ $Date: 2009-03-26 14:53:00 +0100 (Thu, 26 Mar 2009) $
054     */
055    public class MCRAVExtRealHelix extends MCRAudioVideoExtender {
056    
057        /** The logger */
058        private final static Logger LOGGER = Logger.getLogger(MCRAVExtRealHelix.class);
059    
060        public MCRAVExtRealHelix() {
061        }
062    
063        public void init(MCRFileReader file) throws MCRPersistenceException {
064            super.init(file);
065    
066            MCRConfiguration config = MCRConfiguration.instance();
067            String prefix = "MCR.IFS.AVExtender." + file.getStoreID() + ".";
068    
069            baseMetadata = config.getString(prefix + "ViewSourceBaseURL");
070    
071            try {
072                String data = getMetadata(baseMetadata + file.getStorageID());
073    
074                String sSize = getBetween("File Size:</strong>", "Bytes", data, "0");
075                String sBitRate = getBetween("Bit Rate:</strong>", "Kbps", data, "0.0");
076                String sFrameRate = getBetween("Frame Rate: </strong>", "fps", data, "0.0");
077                String sDuration = getBetween("Duration:</strong>", "<br>", data, "0:0.0");
078                String sType = getBetween("Stream:</strong>", "<br>", data, "");
079    
080                bitRate = Math.round(1024 * Float.valueOf(sBitRate).floatValue());
081    
082                StringTokenizer st1 = new StringTokenizer(sFrameRate, " ,");
083    
084                while (st1.hasMoreTokens()) {
085                    double value = Double.valueOf(st1.nextToken()).doubleValue();
086                    frameRate = Math.max(frameRate, value);
087                }
088    
089                mediaType = (frameRate > 0);
090    
091                StringTokenizer st2 = new StringTokenizer(sDuration, ":.");
092                durationMinutes = Integer.parseInt(st2.nextToken());
093                durationSeconds = Integer.parseInt(st2.nextToken());
094    
095                if (Integer.parseInt(st2.nextToken()) > 499) {
096                    durationSeconds += 1;
097    
098                    if (durationSeconds > 59) {
099                        durationMinutes += 1;
100                        durationSeconds = 0;
101                    }
102                }
103    
104                StringTokenizer st3 = new StringTokenizer(sSize, ",");
105                StringBuffer sb = new StringBuffer();
106    
107                while (st3.hasMoreTokens())
108                    sb.append(st3.nextToken());
109    
110                size = Long.parseLong(sb.toString());
111    
112                durationHours = (durationMinutes / 60);
113                durationMinutes = durationMinutes - (durationHours * 60);
114    
115                if (sType.indexOf("MPEG Layer 3") >= 0) {
116                    contentTypeID = "mp3";
117                    mediaType = AUDIO;
118                } else if (sType.indexOf("MPEG") >= 0) {
119                    contentTypeID = "mpegvid";
120                    mediaType = VIDEO;
121                } else if (sType.indexOf("RealVideo") >= 0) {
122                    contentTypeID = "realvid";
123                } else if (sType.indexOf("RealAudio") >= 0) {
124                    contentTypeID = "realaud";
125                } else if (sType.indexOf("Wave File") >= 0) {
126                    contentTypeID = "wav";
127                    mediaType = AUDIO;
128                } else // should be one of "wma" "wmv" "asf"
129                {
130                    contentTypeID = file.getContentTypeID();
131    
132                    if (contentTypeID.equals("wma")) {
133                        mediaType = AUDIO;
134                    } else {
135                        mediaType = VIDEO;
136                    }
137                }
138    
139                if (" wma wmv asf asx ".indexOf(" " + contentTypeID + " ") != -1) {
140                    basePlayerStarter = config.getString(prefix + "AsxGenBaseURL");
141                    playerDownloadURL = config.getString(prefix + "MediaPlayerURL");
142                } else {
143                    basePlayerStarter = config.getString(prefix + "RamGenBaseURL");
144                    playerDownloadURL = config.getString(prefix + "RealPlayerURL");
145                }
146    
147                URLConnection con = getConnection(basePlayerStarter + file.getStorageID());
148                playerStarterCT = con.getContentType();
149            } catch (Exception exc) {
150                String msg = "Error parsing metadata from Real Server ViewSource: " + file.getStorageID();
151                LOGGER.warn(msg, exc);
152            }
153        }
154    
155        public void getPlayerStarterTo(OutputStream out, String startPos, String stopPos) throws MCRPersistenceException {
156            if (basePlayerStarter == null || basePlayerStarter.length() < 8) {
157                String msg = "Temporary Failure. Could not start streaming of file: " + file.getPath();
158                throw new MCRPersistenceException(msg);
159            }
160    
161            try {
162                StringBuffer cgi = new StringBuffer(basePlayerStarter);
163                cgi.append(file.getStorageID());
164    
165                if ((startPos != null) || (stopPos != null)) {
166                    cgi.append("?");
167                }
168    
169                if (startPos != null) {
170                    cgi.append("start=").append(startPos);
171                }
172    
173                if ((startPos != null) && (stopPos != null)) {
174                    cgi.append("&");
175                }
176    
177                if (stopPos != null) {
178                    cgi.append("end=").append(stopPos);
179                }
180    
181                URLConnection connection = getConnection(cgi.toString());
182                forwardData(connection, out);
183            } catch (IOException exc) {
184                String msg = "Could not send player starter file";
185                throw new MCRPersistenceException(msg, exc);
186            }
187        }
188    }