Package ch.rolandschaer.ascrblr.radio

Source Code of ch.rolandschaer.ascrblr.radio.RadioService$SessionToken

/* Copyright (c) 2007 Roland Sch�r
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package ch.rolandschaer.ascrblr.radio;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.HashMap;

import ch.rolandschaer.ascrblr.HttpRequest;
import ch.rolandschaer.ascrblr.Service;
import ch.rolandschaer.ascrblr.Session;
import ch.rolandschaer.ascrblr.HttpRequest.RequestType;
import ch.rolandschaer.ascrblr.util.MD5Util;
import ch.rolandschaer.ascrblr.util.ResponseUtil;
import ch.rolandschaer.ascrblr.util.ServiceException;


public class RadioService extends Service {
 
  /** Base URL for radio service */
  private static final String SERVICE_BASEURL = "http://ws.audioscrobbler.com/";
 
  /** Version string */
  private static final String VERSION = "1.1.1";
 
  /** Response type */
  //TODO: Find out what responses are possible here...
  public enum ResponseType {
    FAILED, OK
  }
 
  /** Control command */
  public enum Command {
    SKIP { public String toString(){return "skip"; } },
    BAN { public String toString(){return "ban"; } },
    LOVE { public String toString(){return "love"; } }
  }
 
  /** Authentication token */
  private AuthToken authToken;
 
  /** Session token */
  private SessionToken sessionToken;
 
  /** Indicates if radio is already tuned to a station */
  private boolean isTunedIn = false;
 
  /**
   * Default constructor.
   */
  public RadioService() {}
 
  /**
     * Gets the current tuned in MP3 stream from the service.
     *
     * @return BufferedInputStream of the MP3 file
     * @throws IOException
     * @throws ServiceException
     */
  public BufferedInputStream getMp3Stream() throws IOException, ServiceException {
   
    if(!isTunedIn) {
      throw new IllegalStateException("Method tuneInStation() has to be called first");
    }
   
    URL url = new URL(sessionToken.getStreamingUrl());
    HttpRequest request = requestFactory.getRequest(RequestType.STREAM, url)
   
    if(connectTimeout>0) {
      request.setConnectTimeout(connectTimeout);
    }
   
    if(readTimeout>0) {
      request.setReadTimeout(readTimeout);
    }

    // Execute the request
    request.execute();     
   
    // Handle response
    return  new BufferedInputStream(request.getResponseStream());
 
  }

  /**
   * Sets the service credentials used for authentication.
   * By calling this method a request of type HANDSHAKE is
   * done to obtain a valid session.
   *
   * @param username
   *            Audioscrobbler user name
   * @param password
   *            Audioscrobbler password
   * @throws IOException
   * @throws ServiceException
   */
  public void setCredentials(String username, String password) throws IOException, ServiceException {
   
    this.authToken = new AuthToken(username, password);
   
    handshake();
   
  }

  /**
     * Tunes in a specific radio station.
     *
     * @param stationUrl
     *            Last.fm Station URL in form of lastfm://<type>/<descriptor>
     * @throws IOException
     * @throws ServiceException
     */
  public void tuneInStation(StationUrl stationUrl) throws IOException, ServiceException {
   
    doRequest(
        RequestType.TUNEIN,
        SERVICE_BASEURL +
        "radio/" +
        "adjust.php" +
        "?session=" + sessionToken.getSessionId() +
        "&url=" + stationUrl.toString() +
        "&debug=0"
    );
   
    isTunedIn = true;

  }

  /*
   * (non-Javadoc)
   * @see ch.rolandschaer.ascrblr.Service#getVersion()
   */
  public String getVersion() {
   
    return VERSION;
   
  }

  /**
   * Returns a <code>MetaData</code> object of the currently playing
   * track.
   *
   * @return <code>MetaData</code>object of the currently playing track.
   * @throws IOException
   * @throws ServiceException
   */
  public MetaData getMetaData() throws IOException, ServiceException {
     
      if(!isTunedIn) {
            throw new IllegalStateException("Method tuneInStation() has to be called first");
        }
     
      InputStream resultStream = null;
        MetaData data = null;
       
        try {

            URL url = new URL(
                SERVICE_BASEURL +
                "radio/np.php" +
                "?session=" +sessionToken.getSessionId() +
                "&debug=0"
            );
            HttpRequest request = requestFactory.getRequest(RequestType.QUERY, url);
           
            if(connectTimeout>0) {
                request.setConnectTimeout(connectTimeout);
            }
           
            if(readTimeout>0) {
                request.setReadTimeout(readTimeout);
            }

            // Execute the request
            request.execute();         
           
            // Handle response
            resultStream = request.getResponseStream();
            HashMap<String,String> parameter = ResponseUtil.getParameterMap(resultStream);

            if( !parameter.containsKey("streaming")
                    || "false".equals(parameter.get("streaming")) ) {
                throw new IllegalStateException("Method getMp3Stream() has to be called first.");
            }
           
            logger.info("Received track data " + parameter);
           
            data = new MetaData(parameter);  
            return data;

        } finally {
            if (resultStream != null) {
                resultStream.close();
            }
        }
  }
 
  /**
   * Executes a command to control the <code>BufferedInputStream</code>.
   *
   * @return Returns <code>true</code> if the command was successful,
   *         <code>false</code> otherwise
   * @throws IOException
   * @throws ServiceException
   */
  public void executeCommand(Command cmd) throws IOException, ServiceException {
   
    doRequest(
        RequestType.NOTIFY,
        SERVICE_BASEURL +
        "radio/" +
        "control.php" +
        "?session=" + sessionToken.getSessionId() +
        "&command=" + cmd.toString() +
        "&debug=0"
    );
   
  }

  /**
   * Handles handshake with the Webserver.
   *
   * @throws IOException
   * @throws ServiceException
   */
  private void handshake() throws IOException, ServiceException {
   
    isTunedIn = false;
   
    doRequest(
          RequestType.HANDSHAKE,
          SERVICE_BASEURL + "radio/handshake.php" +
          "?version=" + VERSION +
          "&platform=" +
          "&username=" + authToken.getUsername() +
          "&passwordmd5=" + authToken.getAuthToken() +
          "&debug=0" +
          "&partner="
        );
   
  }
 
  /*
   * (non-Javadoc)
   * @see ch.rolandschaer.ascrblr.Service#handleResponse(java.io.InputStream)
   */
  protected void handleResponse(InputStream responseStream) throws IOException, ServiceException {
   
      HashMap<String,String> parameter = ResponseUtil.getParameterMap(responseStream);
   
    if( (parameter.containsKey("session") && !parameter.get("session").equals("FAILED"))
        || (parameter.containsKey("response") && parameter.get("response").equals("OK") ) ) {
      //Handle handshake response
      if(parameter.containsKey("session") && parameter.get("session").length()==32){
        sessionToken =  new SessionToken(parameter.get("session"),
            parameter.get("stream_url"),
            parameter.get("base_url"),
            parameter.get("base_path")
        );
      }
    } else {
      handleErrorResponse(parameter);
    }
       
  }
 
  /**
   * Handles error response.
   *
   * @param response
   *            Web server response in form of a <code>HashMap</code>. The
   *            response is sent in form of a parameter list e.g.
   *            session=failed divided by Unix new lines.
   *
   * @throws ServiceException
   */
  private void handleErrorResponse(HashMap<String,String> response) throws ServiceException {
   
    String responseType = response.get("session");
   
    logger.info("Handling error response " + response);
   
    if( responseType.startsWith(ResponseType.FAILED.toString()) ) {
     
      throw new ServiceException(response.get("msg"));
     
   
  }

 
  /**
   * Encapsulates session data provided by the service
   */
  public static class SessionToken implements Session {

      /** Session identifier */
    private String sessionId;
   
    /** Streaming URL */
    private String streamingUrl;
   
    /** Service base URL */
    private String baseUrl;
   
    /** Service base path */
    private String basePath;

    /**
         * Session token which holds relevant session info.
         *
         * @param sessionId
         *            Session identifier given by the service
         * @param streamingUrl
         *            Streaming URL
         * @param baseUrl
         *            Service base URL
         * @param basePath
         *            Service base path
         */
    public SessionToken(String sessionId, String streamingUrl, String baseUrl, String basePath) {
      this.sessionId = sessionId;
      this.streamingUrl = streamingUrl;
      this.baseUrl = baseUrl;
      this.basePath = basePath;
    }

    public String getSessionId() {
      return sessionId;
    }
   
    public String getStreamingUrl() {
      return streamingUrl;
    }
   
    public String getBaseUrl() {
      return baseUrl;
    }
   
    public String getBasePath() {
      return basePath;
    }

  }

  /**
   * Encapsulates authentication token which is used during handshake.
   */
  public static class AuthToken {

    private String username;

    private String passwordHash;

    /**
         * Authentication token needed to autenticate on the service.
         *
         * @param username
         *            last.fm username
         * @param password
         *            last.fmm password
         * @throws ServiceException
         */
    public AuthToken(String username, String password) throws ServiceException {
      this.username = username;
      this.passwordHash = MD5Util.getMD5(password);
    }

    public String getUsername() { return username; }

    /**
     * Authentication token used by the service. The token is built as
     * follows: <code>md5(password)
     *
     * @param timestamp Unix time stamp
     * @return
     * @throws ServiceException
     */
    public String getAuthToken() throws ServiceException {
      return passwordHash;
    }

  }
}
TOP

Related Classes of ch.rolandschaer.ascrblr.radio.RadioService$SessionToken

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.