Package com.vessosa.g15lastfmplayer.model

Source Code of com.vessosa.g15lastfmplayer.model.MainModel

package com.vessosa.g15lastfmplayer.model;

import java.awt.Desktop;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.AudioDevice;
import javazoom.jl.player.FactoryRegistry;
import javazoom.jl.player.Player;
import net.roarsoftware.lastfm.Authenticator;
import net.roarsoftware.lastfm.Caller;
import net.roarsoftware.lastfm.Playlist;
import net.roarsoftware.lastfm.Radio;
import net.roarsoftware.lastfm.Result;
import net.roarsoftware.lastfm.Session;
import net.roarsoftware.lastfm.Track;
import net.roarsoftware.lastfm.scrobble.ResponseStatus;
import net.roarsoftware.lastfm.scrobble.Scrobbler;
import net.roarsoftware.lastfm.scrobble.Source;
import net.roarsoftware.xml.DomElement;

import org.apache.log4j.Logger;

import com.vessosa.g15lastfmplayer.G15LastfmPlayer;
import com.vessosa.g15lastfmplayer.controller.Controller;
import com.vessosa.g15lastfmplayer.util.Config;
import com.vessosa.g15lastfmplayer.util.ELCDScreen;
import com.vessosa.g15lastfmplayer.util.MSNSendPlayingInfo;
import com.vessosa.g15lastfmplayer.util.mvc.DefaultModel;

public class MainModel extends DefaultModel {
  private static final Logger LOGGER = Logger.getLogger(MainModel.class);
  private boolean isPlaying = false;
  private boolean continuePlaying = false;
  private Session session;
  private Player player;
  private Thread playThread;
  private Thread progressThread;
  private Track currentTrack;
  private long startPlaybackTime;
  private Scrobbler scrobbler;
  private boolean hasSkipped = false;
  private Radio currentRadio;
  private MSNSendPlayingInfo sendMsnInfo;

  public MainModel() {
  }

  public void setShowStatuswMessage(final String message, final int displaySec) {
    new Thread() {

      @Override
      public void run() {
        firePropertyChange(Controller.STATUS_MESSAGE, null, message);
        firePropertyChange(Controller.SHOW_STATUS_MESSAGE, null, true);
        firePropertyChange(Controller.SHOW_MUSIC_PROGRESS, null, false);

        // show progress again
        try {
          Thread.sleep(displaySec * 1000);
          firePropertyChange(Controller.SHOW_STATUS_MESSAGE, null, false);
          if (isPlaying)
            firePropertyChange(Controller.SHOW_MUSIC_PROGRESS, null, true);
          else
            firePropertyChange(Controller.SHOW_MUSIC_PROGRESS, null, false);
        } catch (InterruptedException e) {
          LOGGER.debug(e);
        }

      }

    }.start();
  }

  public void setShowStatuswMessage(String message) {
    setShowStatuswMessage(message, 5);
  }

  public void setMusicName(String musicName) {
    LOGGER.debug("Setting music: " + musicName);
    firePropertyChange(Controller.MUSIC_NAME, null, musicName);
  }

  public void processSearchAndPlay(String radioToSearch) throws Exception {
    firePropertyChange(Controller.WORKING, null, true);
    Session session = login(Config.getValue(Config.USER), Config.getValue(Config.PASSWORD));
    Radio radio = tuneStation(radioToSearch, session, false);
    currentRadio = radio;
    processStop();
    continuePlaying = true;
    keepPlaying(radio, session);
  }

  public void processPlay() throws Exception {
    if (isPlaying) {
      LOGGER.info("Already playing, ignoring");
    } else {
      firePropertyChange(Controller.WORKING, null, true);
      Session session = login(Config.getValue(Config.USER), Config.getValue(Config.PASSWORD));
      String recentStation = getRecentStation(Config.getValue(Config.USER), session);
      Radio radio = tuneStation(recentStation, session, true);
      currentRadio = radio;
      continuePlaying = true;
      keepPlaying(radio, session);
    }
  }

  public void processBan() throws Exception {
    if (isPlaying && currentTrack != null) {
      Session session = login(Config.getValue(Config.USER), Config.getValue(Config.PASSWORD));
      Result result = Track.ban(currentTrack.getArtist(), currentTrack.getName(), session);
      if (result.isSuccessful()) {
        LOGGER.debug("LOVE IT!");
        setShowStatuswMessage("BANNED");
      } else {
        LOGGER.debug("Not possible to set BAN: " + result.getErrorMessage());
      }
      processSkip();
    }
  }

  public void processLove() throws Exception {
    if (isPlaying && currentTrack != null) {
      Session session = login(Config.getValue(Config.USER), Config.getValue(Config.PASSWORD));
      Result result = Track.love(currentTrack.getArtist(), currentTrack.getName(), session);
      if (result.isSuccessful()) {
        LOGGER.debug("LOVE IT!");
        setShowStatuswMessage("LOVE IT!");
      } else {
        LOGGER.debug("Not possible to set Love: " + result.getErrorMessage());
      }

    }
  }

  public void processStop() {
    while (isPlaying) {
      if (player != null) {
        hasSkipped = true;
        continuePlaying = false;
        player.close();
      }
    }
    setMusicName("Stopped");
    getSendMsnInfo().sendPlayingInfo("", "", "", false);
    setShowStatuswMessage("Stopped", 20);
  }

  private String getPreparedStationName(Radio radio) {
    // necessary to convert accent chars to normal char due not compatible
    // with internal font
    String preparedRadio = "No station";
    if (radio != null) {
      preparedRadio = radio.getStationName().toLowerCase().replaceAll("[�����]", "a");
      preparedRadio = preparedRadio.toLowerCase().replaceAll("[����]", "e");
      preparedRadio = preparedRadio.toLowerCase().replaceAll("[����]", "i");
      preparedRadio = preparedRadio.toLowerCase().replaceAll("[�����]", "o");
      preparedRadio = preparedRadio.toLowerCase().replaceAll("[����]", "u");
    }
    return preparedRadio;
  }

  public void processSkip() {
    while (isPlaying) {
      if (player != null) {
        hasSkipped = true;
        player.close();
      }
    }
  }

  private void scrobbleSong(Session session) {
    long now = System.currentTimeMillis() / 1000;
    long totalPlayed = now - startPlaybackTime;
    if (totalPlayed > 40) {
      try {
        Scrobbler scrobbler = getScrobbler(session);
        if (scrobbler != null) {
          ResponseStatus status = scrobbler.submit(currentTrack.getArtist(), currentTrack.getName(),
              currentTrack.getAlbum(), currentTrack.getDuration(), currentTrack.getPosition(),
              Source.USER, startPlaybackTime);
          LOGGER.debug("Submit OK: " + status.ok());
        } else {
          LOGGER.error("Can't scrobble now");
        }
      } catch (Exception e) {
        LOGGER.debug(e);
      }
    }
  }

  InputStream in;

  public void playStreaming(String path) {
    if (isPlaying)
      return;
    try {
      AudioDevice dev = getAudioDevice();
      player = new Player(getURLInputStream(path), dev);
      isPlaying = true;
      player.play();
      in.close();
      LOGGER.debug("------------------------------------------------- FIM DO PLAY");
      isPlaying = false;
    } catch (UnknownHostException e) {
      showErrorMessage("Last.fm seems to be down, please try again later.");
    } catch (IOException e) {
      processStop();
      firePropertyChange(Controller.MUSIC_NAME, null, "ERROR - STOPPED");
      LOGGER.debug(e);
    } catch (Exception e) {
      processStop();
      LOGGER.debug("Exception: " + e.getCause());
    }
  }

  private InputStream getURLInputStream(String urlPath) throws Exception {
    if (in != null)
      in.close();

    URL url = new URL(urlPath);
    in = url.openStream();
    BufferedInputStream bin = new BufferedInputStream(in);
    return bin;
  }

  private AudioDevice getAudioDevice() throws JavaLayerException {
    return FactoryRegistry.systemRegistry().createAudioDevice();
  }

  private ResponseStatus scrobblerResponse = new ResponseStatus(ResponseStatus.FAILED);

  private Scrobbler getScrobbler(Session session) {
    if (!scrobblerResponse.ok()) {
      try {
        scrobbler = Scrobbler.newScrobbler("tst", "1.0", Config.getValue(Config.USER));
        scrobblerResponse = scrobbler.handshake(session);
      } catch (Exception e) {
        LOGGER.debug(e);
        return null;
      }
    }
    return scrobbler;
  }

  private void prepareProgressBar() {
    if (player != null) {
      if (isPlaying) {
        int duration = currentTrack.getDuration() * 1000;
        int cPos = (player.getPosition() * 100) / duration;
        firePropertyChange(Controller.MUSIC_PROGRESS, null, cPos);
      }
    }
  }

  private void showErrorMessage(String string) {
    LOGGER.error(string);
  }

  public List<String> getRecentStations(String user, Session session) {
    List<String> recentStations = new ArrayList<String>();
    Result result = Caller.getInstance().call("user.getRecentStations", session, "user", user);
    if (!result.isSuccessful())
      return Collections.emptyList();
    DomElement element = result.getContentElement();
    for (DomElement stationElement : element.getChildren("station")) {
      // for (DomElement lista : stationElement.getChildren()) {
      // LOGGER.debug(lista.getTagName());
      // }
      // for (DomElement urlElement : stationElement.getChildren("name"))
      // {
      // LOGGER.debug(urlElement.getText());
      // }
      for (DomElement urlElement : stationElement.getChildren("url")) {
        // LOGGER.debug(urlElement.getText());
        recentStations.add(urlElement.getText());
      }
      // radioFromElement(domElement);
      // radios.add(radioFromElement(domElement));
      // tracks.add(Track.trackFromElement(domElement));
    }
    return recentStations;
  }

  public void callSoftButton1() {
  }

  public void callSearch() {
    firePropertyChange(Controller.SHOW_SEARCH_DIALOG, false, true);
    setShowStatuswMessage("Search", 14);
  }

  private Session login(String user, String password) throws Exception {
    // Authenticate user
    if (session == null) {
      String apiKey = "90120304ba34b682c26aec08425d80e4";
      String apiSig = "a35553cb9a5bb4be934a284ffb114b46";
      try {
        LOGGER.debug("Authenticating...");
        session = Authenticator.getMobileSession(user, password, apiKey, apiSig);

      } catch (Exception e) {
        if (e instanceof UnknownHostException) {
          showErrorMessage("Last.fm seens to be down, please try again later.");
        }
      }
    }
    if (session == null) {
      LOGGER.debug("Could not login on Last.fm, may be wrong password?");
      throw new Exception("Could not login on Last.fm, may be wrong password?");
    }
    return session;
  }

  private Radio tuneStation(String radioName, Session session, boolean tuneKnownRadio) throws Exception {
    Radio radio = null;
    if (tuneKnownRadio) {
      // Tune a real radio
      radio = Radio.tune(radioName, Locale.US, session);
    } else {
      // Tune for similar artists
      radio = Radio.tune(Radio.RadioStation.similarArtists(radioName), session);
    }
    if (radio == null) {
      throw new Exception("Nothing found with this radio name: " + radioName);
    } else {
      LOGGER.debug("Radio tunned: " + getPreparedStationName(radio));
    }
    return radio;
  }

  private String getRecentStation(String user, Session session) {
    List<String> recentStations = new ArrayList<String>();
    Result result = Caller.getInstance().call("user.getRecentStations", session, "user", user);
    if (!result.isSuccessful())
      return null;
    DomElement element = result.getContentElement();
    for (DomElement stationElement : element.getChildren("station")) {
      // for (DomElement lista : stationElement.getChildren()) {
      // LOGGER.debug(lista.getTagName());
      // }
      // for (DomElement urlElement : stationElement.getChildren("name"))
      // {
      // LOGGER.debug(urlElement.getText());
      // }
      for (DomElement urlElement : stationElement.getChildren("url")) {
        // LOGGER.debug(urlElement.getText());
        recentStations.add(urlElement.getText());
      }
      // radioFromElement(domElement);
      // radios.add(radioFromElement(domElement));
      // tracks.add(Track.trackFromElement(domElement));
    }
    return recentStations.get(0);
  }

  private List<Track> getPlayListTracks(Radio radio) {
    Playlist playlist = radio.getPlaylist();
    return new ArrayList<Track>(playlist.getTracks());
  }

  private void keepPlaying(final Radio radio, final Session session) {
    prepareProgressThread();
    setShowStatuswMessage(getPreparedStationName(radio), 20);
    playThread = new Thread() {

      @Override
      public void run() {
        List<Track> tracks = new ArrayList<Track>();
        while (continuePlaying) {
          if (tracks.size() == 0) {
            LOGGER.debug("Retrieving new playlist");
            tracks = getPlayListTracks(radio);
            LOGGER.debug("Retrieved " + tracks.size() + " tracks");
          }
          setShowStatuswMessage(getPreparedStationName(radio), 20);
          startPlaybackTime = System.currentTimeMillis() / 1000;
          currentTrack = tracks.get(0);
          nowPlaying(session, currentTrack);
          firePropertyChange(Controller.WORKING, null, false);
          playStreaming(currentTrack.getLocation());
          if (!hasSkipped)
            scrobbleSong(session);

          if (tracks.size() > 0) {
            tracks.remove(0);
            LOGGER.debug("Tracks available: " + tracks.size());
          }
        }
      }
    };

    playThread.setName("playThread");
    playThread.start();
  }

  private void nowPlaying(final Session session, Track track) {
    new Thread() {

      @Override
      public void run() {
        try {
          getSendMsnInfo().sendPlayingInfo(currentTrack.getArtist(), currentTrack.getName(),
              currentTrack.getAlbum(), true);
          setMusicName(currentTrack.getArtist() + " - " + currentTrack.getName());
          Scrobbler scrobbler = getScrobbler(session);
          if (scrobbler != null) {
            ResponseStatus status = scrobbler.nowPlaying(currentTrack.getArtist(), currentTrack.getName());
            LOGGER.debug("Submit OK: " + status.ok());
          } else {
            LOGGER.error("Can't scrobble now");
          }
        } catch (Exception e) {
          LOGGER.debug("Error on calling nowPlaying: " + e.getMessage());
        }

      }

    }.start();
  }

  private void prepareProgressThread() {
    firePropertyChange(Controller.SET_LCD_SCREEN, null, ELCDScreen.SCROLLING_TEXT_VIEW);
    if (progressThread == null) {
      progressThread = new Thread() {
        @Override
        public void run() {
          for (;;)
            prepareProgressBar();
        }
      };
      progressThread.setName("progressThread");
      progressThread.start();
    }
  }

  public MSNSendPlayingInfo getSendMsnInfo() {
    if (sendMsnInfo == null) {
      sendMsnInfo = new MSNSendPlayingInfo();
    }
    return sendMsnInfo;
  }

  public void callUpdate() {
    LOGGER.debug("Checking for Updates");
    new Thread() {

      @Override
      public void run() {
        String lastVersion = null;
        try {
          URL projectSite = new URL("http://code.google.com/p/g15lastfm/");
          URLConnection urlC = projectSite.openConnection();
          BufferedReader in = new BufferedReader(new InputStreamReader(urlC.getInputStream()));
          String inputLine;
          while ((inputLine = in.readLine()) != null) {
            if (inputLine.contains("<strong>Current version:")) {
              lastVersion = inputLine;
              break;
            }
          }
          in.close();

          if (lastVersion != null && lastVersion.length() > 0) {
            lastVersion = lastVersion.substring(lastVersion.indexOf("Current version:") + 16);
            lastVersion = lastVersion.substring(0, lastVersion.indexOf("</strong>")).trim();
            LOGGER.debug("last Version=" + lastVersion);
          }
          if (!lastVersion.equals(G15LastfmPlayer.getVersion()))
            LOGGER.debug("Not necessary to update");
          else {
            LOGGER.debug("New update found!");
            SwingUtilities.invokeLater(new Runnable() {

              @Override
              public void run() {
                if (JOptionPane.showConfirmDialog(null,
                    "New version of G15Lastfm is available to download!",
                    "New Update for G15Lastfm", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
                  LOGGER.debug("User choose to update, opening browser.");
                  Desktop desktop = Desktop.getDesktop();
                  try {
                    desktop.browse(new URI("http://code.google.com/p/g15lastfm/"));
                  } catch (IOException e) {
                    LOGGER.debug(e);
                  } catch (URISyntaxException e) {
                    LOGGER.debug(e);
                  }
                } else {
                  LOGGER.debug("User choose to not update.");
                }
              }

            });

          }

        } catch (Exception e) {
          LOGGER.debug(e);
        }

      }

    }.start();
  }
}
TOP

Related Classes of com.vessosa.g15lastfmplayer.model.MainModel

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.