Skip to content

Commit

Permalink
Update protocol to minor version 95 (0x5F). Add support for finding r…
Browse files Browse the repository at this point in the history
…eplacement tracks.
  • Loading branch information
fxb committed May 9, 2010
1 parent e99bab6 commit cd05bb1
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 84 deletions.
22 changes: 22 additions & 0 deletions src/de/felixbruns/jotify/Jotify.java
Expand Up @@ -168,6 +168,28 @@ public interface Jotify extends Runnable, Player {
*/
public List<Track> browseTracks(List<String> ids) throws TimeoutException;

/**
* Request a replacement track.
*
* @param track The track to search the replacement for.
*
* @return A {@link Track} object.
*
* @see Track
*/
public Track replacement(Track track) throws TimeoutException;

/**
* Request multiple replacement track.
*
* @param tracks The tracks to search the replacements for.
*
* @return A list of {@link Track} objects.
*
* @see Track
*/
public List<Track> replacement(List<Track> tracks) throws TimeoutException;

/**
* Get stored user playlists.
*
Expand Down
176 changes: 113 additions & 63 deletions src/de/felixbruns/jotify/JotifyConnection.java
Expand Up @@ -22,33 +22,37 @@
import de.felixbruns.jotify.util.*;

public class JotifyConnection implements Jotify, CommandListener {
private Session session;
private Protocol protocol;
private boolean running;
private User user;
private Semaphore userSemaphore;
private SpotifyOggPlayer oggPlayer;
private Cache cache;
private float volume;
private long timeout;
private TimeUnit unit;
/*
* Values for browsing media.
*/
private static final int BROWSE_ARTIST = 1;
private static final int BROWSE_ALBUM = 2;
private static final int BROWSE_TRACK = 3;

/**
* Enum for browsing media.
/*
* Session and protocol associated with this connection.
*/
private enum BrowseType {
ARTIST(1), ALBUM(2), TRACK(3);

private int value;

private BrowseType(int value){
this.value = value;
}

public int getValue(){
return this.value;
}
}
protected Session session;
protected Protocol protocol;

/*
* User information.
*/
private User user;
private Semaphore userSemaphore;

/*
* Player and cache.
*/
private Player player;
private Cache cache;

/*
* Status and timeout.
*/
private boolean running;
private long timeout;
private TimeUnit unit;

/**
* Create a new Jotify instance using the default {@link Cache}
Expand Down Expand Up @@ -76,9 +80,8 @@ public JotifyConnection(Cache cache, long timeout, TimeUnit unit){
this.running = false;
this.user = null;
this.userSemaphore = new Semaphore(2);
this.oggPlayer = null;
this.player = null;
this.cache = cache;
this.volume = 1.0f;
this.timeout = timeout;
this.unit = unit;

Expand All @@ -97,6 +100,16 @@ public void setTimeout(long timeout, TimeUnit unit){
this.unit = unit;
}

/**
* Set timeout for requests.
*
* @param seconds Timeout in seconds to use.
*/
public void setTimeout(long seconds){
this.timeout = seconds;
this.unit = TimeUnit.SECONDS;
}

/**
* Login to Spotify using the specified username and password.
*
Expand Down Expand Up @@ -327,7 +340,7 @@ public Image image(String id) throws TimeoutException {
*
* @see BrowseType
*/
private Object browse(BrowseType type, String id) throws TimeoutException {
private Object browse(int type, String id) throws TimeoutException {
/*
* Check if id is a 32-character hex string,
* if not try to parse it as a Spotify URI.
Expand All @@ -336,9 +349,9 @@ private Object browse(BrowseType type, String id) throws TimeoutException {
try{
Link link = Link.create(id);

if((type.equals(BrowseType.ARTIST) && !link.isArtistLink()) ||
(type.equals(BrowseType.ALBUM) && !link.isAlbumLink()) ||
(type.equals(BrowseType.TRACK) && !link.isTrackLink())){
if((type == BROWSE_ARTIST && !link.isArtistLink()) ||
(type == BROWSE_ALBUM && !link.isAlbumLink()) ||
(type == BROWSE_TRACK && !link.isTrackLink())){
throw new IllegalArgumentException(
"Browse type doesn't match given Spotify URI."
);
Expand All @@ -359,7 +372,7 @@ private Object browse(BrowseType type, String id) throws TimeoutException {

/* Send browse request. */
try{
this.protocol.sendBrowseRequest(callback, type.getValue(), id);
this.protocol.sendBrowseRequest(callback, type, id);
}
catch(ProtocolException e){
return null;
Expand All @@ -383,7 +396,7 @@ private Object browse(BrowseType type, String id) throws TimeoutException {
*/
public Artist browseArtist(String id) throws TimeoutException {
/* Browse. */
Object artist = this.browse(BrowseType.ARTIST, id);
Object artist = this.browse(BROWSE_ARTIST, id);

if(artist instanceof Artist){
return (Artist)artist;
Expand Down Expand Up @@ -418,7 +431,7 @@ public Artist browse(Artist artist) throws TimeoutException {
*/
public Album browseAlbum(String id) throws TimeoutException {
/* Browse. */
Object album = this.browse(BrowseType.ALBUM, id);
Object album = this.browse(BROWSE_ALBUM, id);

if(album instanceof Album){
return (Album)album;
Expand Down Expand Up @@ -452,7 +465,7 @@ public Album browse(Album album) throws TimeoutException {
*/
public Track browseTrack(String id) throws TimeoutException {
/* Browse. */
Object object = this.browse(BrowseType.TRACK, id);
Object object = this.browse(BROWSE_TRACK, id);

if(object instanceof Result){
Result result = (Result)object;
Expand Down Expand Up @@ -542,7 +555,7 @@ public List<Track> browseTracks(List<String> ids) throws TimeoutException {

/* Send browse request. */
try{
this.protocol.sendBrowseRequest(callback, BrowseType.TRACK.getValue(), ids);
this.protocol.sendBrowseRequest(callback, BROWSE_TRACK, ids);
}
catch(ProtocolException e){
return null;
Expand Down Expand Up @@ -583,6 +596,48 @@ public List<Track> browse(List<Track> tracks) throws TimeoutException {
return this.browseTracks(ids);
}

/**
* Request a replacement track.
*
* @param track The track to search the replacement for.
*
* @return A {@link Track} object.
*
* @see Track
*/
public Track replacement(Track track) throws TimeoutException {
return this.replacement(Arrays.asList(track)).get(0);
}

/**
* Request multiple replacement track.
*
* @param tracks The tracks to search the replacements for.
*
* @return A list of {@link Track} objects.
* @throws TimeoutException
*
* @see Track
*/
public List<Track> replacement(List<Track> tracks) throws TimeoutException {
/* Create channel callback */
ChannelCallback callback = new ChannelCallback();

/* Send browse request. */
try{
this.protocol.sendReplacementRequest(callback, tracks);
}
catch(ProtocolException e){
return null;
}

/* Get data. */
byte[] data = callback.get(this.timeout, this.unit);

/* Create result from XML. */
return XMLMediaParser.parseResult(data, "UTF-8").getTracks();
}

/**
* Get stored user playlists.
*
Expand Down Expand Up @@ -1477,24 +1532,21 @@ public boolean playlistSetInformation(Playlist playlist, String description, Str
*/
public void play(Track track, int bitrate, PlaybackListener listener) throws TimeoutException, IOException, LineUnavailableException {
/* Stop previous ogg player. */
if(this.oggPlayer != null){
this.oggPlayer.stop();
if(this.player != null){
this.player.stop();

this.oggPlayer = null;
this.player = null;
}

try{
/* Send play request. */
this.protocol.sendPlayRequest();

/* Create a new ogg player. */
this.oggPlayer = new SpotifyOggPlayer(this.protocol);
this.player = new SpotifyOggPlayer(this.protocol);

/* Play track. */
this.oggPlayer.play(track, bitrate, listener);

/* Set volume. */
this.oggPlayer.volume(this.volume);
this.player.play(track, bitrate, listener);
}
catch(Exception e){
e.printStackTrace();
Expand All @@ -1505,28 +1557,28 @@ public void play(Track track, int bitrate, PlaybackListener listener) throws Tim
* Start playing or resume current track.
*/
public void play(){
if(this.oggPlayer != null){
this.oggPlayer.play();
if(this.player != null){
this.player.play();
}
}

/**
* Pause playback of current track.
*/
public void pause(){
if(this.oggPlayer != null){
this.oggPlayer.pause();
if(this.player != null){
this.player.pause();
}
}

/**
* Stop playback of current track.
*/
public void stop(){
if(this.oggPlayer != null){
this.oggPlayer.stop();
if(this.player != null){
this.player.stop();

this.oggPlayer = null;
this.player = null;
}
}

Expand All @@ -1536,8 +1588,8 @@ public void stop(){
* @return Length in milliseconds or -1 if not available.
*/
public int length(){
if(this.oggPlayer != null){
return this.oggPlayer.length();
if(this.player != null){
return this.player.length();
}

return -1;
Expand All @@ -1549,8 +1601,8 @@ public int length(){
* @return Playback position in milliseconds or -1 if not available.
*/
public int position(){
if(this.oggPlayer != null){
return this.oggPlayer.position();
if(this.player != null){
return this.player.position();
}

return -1;
Expand All @@ -1564,8 +1616,8 @@ public int position(){
* @throws IOException If an I/O error occurs while seeking.
*/
public void seek(int ms) throws IOException {
if(this.oggPlayer != null){
this.oggPlayer.seek(ms);
if(this.player != null){
this.player.seek(ms);
}
}

Expand All @@ -1575,8 +1627,8 @@ public void seek(int ms) throws IOException {
* @return A value from 0.0 to 1.0.
*/
public float volume(){
if(this.oggPlayer != null){
return this.oggPlayer.volume();
if(this.player != null){
return this.player.volume();
}

return -1.0f;
Expand All @@ -1588,10 +1640,8 @@ public float volume(){
* @param volume A value from 0.0 to 1.0.
*/
public void volume(float volume){
this.volume = volume;

if(this.oggPlayer != null){
this.oggPlayer.volume(this.volume);
if(this.player != null){
this.player.volume(volume);
}
}

Expand Down
20 changes: 20 additions & 0 deletions src/de/felixbruns/jotify/JotifyPool.java
Expand Up @@ -266,6 +266,26 @@ public List<Track> browseTracks(List<String> ids) throws TimeoutException {
return result;
}

public Track replacement(Track track) throws TimeoutException {
Jotify connection = this.getConnection();

Track result = connection.replacement(track);

this.releaseConnection(connection);

return result;
}

public List<Track> replacement(List<Track> tracks) throws TimeoutException {
Jotify connection = this.getConnection();

List<Track> result = connection.replacement(tracks);

this.releaseConnection(connection);

return result;
}

public PlaylistContainer playlistContainer() throws TimeoutException {
Jotify connection = this.getConnection();

Expand Down

0 comments on commit cd05bb1

Please sign in to comment.