org.jajuk.services.players.WebRadioPlayerImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.jajuk.services.players.WebRadioPlayerImpl.java

Source

/*
 *  Jajuk
 *  Copyright (C) The Jajuk Team
 *  http://jajuk.info
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2
 *  of the License, or any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *  
 */
package org.jajuk.services.players;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.Properties;
import java.util.StringTokenizer;

import org.apache.commons.lang.StringUtils;
import org.jajuk.base.File;
import org.jajuk.events.JajukEvent;
import org.jajuk.events.JajukEvents;
import org.jajuk.events.ObservationManager;
import org.jajuk.services.webradio.WebRadio;
import org.jajuk.util.Conf;
import org.jajuk.util.Const;
import org.jajuk.util.UtilString;
import org.jajuk.util.error.JajukException;
import org.jajuk.util.log.Log;

/**
 * Jajuk web radio player implementation based on Mplayer.
 */
public class WebRadioPlayerImpl extends AbstractMPlayerImpl {
    /**
     * Reader : read information from mplayer like position.
     */
    private class ReaderThread extends Thread {
        /**
         * Implemented to set a useful thread name.
         */
        public ReaderThread() {
            super("WebRadio Reader Thread");
        }

        /* (non-Javadoc)
         * @see java.lang.Thread#run()
         */
        @Override
        public void run() {
            try {
                BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
                String line = null;
                for (;;) {
                    line = in.readLine();
                    if (line == null) {
                        break;
                    }
                    if (line.startsWith(("ICY Info:"))) {
                        //Send an event that web radio info has been updated
                        Properties pDetails = new Properties();
                        String radioTrackDetail = "";
                        // Some stations doesn't include the StreamUrl in the ICY line. Sample :
                        //ICY Info: StreamTitle='-- Now On Air: URB Non-Stop :: Playing: xxx Cilmi - Sweet About Me :: Email the station xxx@yyy.uk --';
                        if (line.contains("';StreamUrl")) {
                            radioTrackDetail = line.substring(line.indexOf("StreamTitle='") + 13,
                                    line.indexOf("';StreamUrl"));
                            // Otherwise, the line should ends with ','
                        } else if (line.endsWith("';")) {
                            radioTrackDetail = line.substring(line.indexOf("StreamTitle='") + 13,
                                    line.length() - 2);
                        } else {
                            // Just in case, we also handle the case where the line doesn't ends with ';
                            radioTrackDetail = line.substring(line.indexOf("StreamTitle='") + 13,
                                    line.length() - 2);
                        }
                        String currentRadioTrack = QueueModel.getCurrentRadio().getName();
                        if (StringUtils.isNotEmpty(radioTrackDetail)) {
                            currentRadioTrack += ":: " + radioTrackDetail;
                        }
                        pDetails.put(Const.DETAIL_CONTENT, QueueModel.getCurrentRadio());
                        pDetails.put(Const.CURRENT_RADIO_TRACK, currentRadioTrack);
                        ObservationManager.notify(new JajukEvent(JajukEvents.WEBRADIO_INFO_UPDATED, pDetails));
                    }
                    bOpening = false;
                    // Search for Exiting (...) pattern
                    if (line.matches(".*\\x2e\\x2e\\x2e.*\\(.*\\).*")) {
                        bEOF = true;
                    }
                }
                // can reach this point at the end of file
                in.close();
                bEOF = true;
                return;
            } catch (Exception e) {
                Log.error(e);
            }
        }
    }

    /**
     * (non-Javadoc).
     * 
     * @param radio 
     * @param fVolume 
     * 
     * @throws IOException Signals that an I/O exception has occurred.
     * @throws JajukException the jajuk exception
     * 
     * @see org.jajuk.players.IPlayerImpl#play(org.jajuk.base.File, float, long,
     * float)
     */
    @Override
    public void play(WebRadio radio, float fVolume) throws IOException, JajukException {
        this.fVolume = fVolume;
        this.bOpening = true;
        this.bEOF = false;
        this.bitPerfect = Conf.getBoolean(Const.CONF_BIT_PERFECT);
        // Start
        ProcessBuilder pb = new ProcessBuilder(buildCommand(radio.getUrl(), 0));
        Log.debug("Using this Mplayer command: {{" + pb.command() + "}}");
        // Set all environment variables format: var1=xxx var2=yyy
        try {
            Map<String, String> env = pb.environment();
            StringTokenizer st = new StringTokenizer(Conf.getString(Const.CONF_ENV_VARIABLES), " ");
            while (st.hasMoreTokens()) {
                StringTokenizer st2 = new StringTokenizer(st.nextToken(), "=");
                env.put(st2.nextToken(), st2.nextToken());
            }
            // If needed, set proxy settings in format:
            // http_proxy=http://username:password@proxy.example.org:8080
            if (Conf.getBoolean(Const.CONF_NETWORK_USE_PROXY)) {
                String sLogin = Conf.getString(Const.CONF_NETWORK_PROXY_LOGIN).trim();
                String sHost = Conf.getString(Const.CONF_NETWORK_PROXY_HOSTNAME).trim();
                int port = Conf.getInt(Const.CONF_NETWORK_PROXY_PORT);
                // Non anonymous proxy
                if (!StringUtils.isBlank(sLogin)) {
                    String sPwd = UtilString.rot13(Conf.getString(Const.CONF_NETWORK_PROXY_PWD));
                    String sProxyConf = "http://" + sLogin + ':' + sPwd + '@' + sHost + ':' + port;
                    env.put("http_proxy", sProxyConf);
                    Log.debug("Using these proxy settings: " + sProxyConf);
                }
                // Anonymous proxy
                else {
                    String sProxyConf = "http://" + sHost + ':' + port;
                    env.put("http_proxy", sProxyConf);
                    Log.debug("Using these proxy settings: " + sProxyConf);
                }
            }
        } catch (Exception e) {
            Log.error(e);
        }
        // Start mplayer
        proc = pb.start();
        // start mplayer replies reader thread
        new ReaderThread().start();
        // if opening, wait, 30 secs max
        int i = 0;
        while (bOpening && i < 30) {
            try {
                Thread.sleep(1000);
                i++;
            } catch (InterruptedException e) {
                Log.error(e);
            }
        }
        // If end of file already reached, it means that file cannot be read
        if (bEOF) {
            throw new JajukException(7);
        }
        // Get track length
        sendCommand("get_time_length");
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.jajuk.players.AbstractMPlayerImpl#play(org.jajuk.base.File, float,
     *      long, float)
     */
    @Override
    public void play(File file, float position, long length, float volume) {
        // nothing to do here...
    }

    /* (non-Javadoc)
    * @see org.jajuk.services.players.IPlayerImpl#getActuallyPlayedTimeMillis()
    */
    @Override
    public long getActuallyPlayedTimeMillis() {
        // makes no sense for webradios
        return 0;
    }
}