Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: jkwatson/Muse-Controller
base: c8d3100ff0
...
head fork: jkwatson/Muse-Controller
compare: 2b1b99d400
Checking mergeability… Don't worry, you can still create the pull request.
  • 3 commits
  • 10 files changed
  • 0 commit comments
  • 1 contributor
Commits on Feb 20, 2012
John Watson kotlin versions of the Main + Gui Main classes. b6875b1
Commits on Mar 31, 2012
John Watson First steps toward a unified MusicPlayer model, supporting both Spoti…
…fy and Pandora
2a8b3ec
John Watson deleted kotlin stuff 2b1b99d
View
8 .idea/ant.xml
@@ -2,6 +2,14 @@
<project version="4">
<component name="AntConfiguration">
<defaultAnt bundledAnt="true" />
+ <buildFile url="file://$PROJECT_DIR$/build.xml">
+ <additionalClassPath />
+ <antReference projectDefault="true" />
+ <customJdkName value="" />
+ <maximumHeapSize value="128" />
+ <maximumStackSize value="2" />
+ <properties />
+ </buildFile>
</component>
</project>
View
16 src/com/sleazyweasel/applescriptifier/AirfoilServlet.java
@@ -15,10 +15,10 @@
private static final String NAME_KEY = "name";
private static final String STATE_KEY = "state";
private AppleScriptTemplate appleScriptTemplate = new AppleScriptTemplateFactory().getActiveTemplate();
- private final MusicPlayer pianobarSupport;
+ private final MusicPlayer musicPlayer;
- public AirfoilServlet(MusicPlayer pianobarSupport) {
- this.pianobarSupport = pianobarSupport;
+ public AirfoilServlet(MusicPlayer musicPlayer) {
+ this.musicPlayer = musicPlayer;
}
@Override
@@ -56,7 +56,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse response) throw
selectApplicationAudioSource(sourceId, response);
} else if (pathInfo.startsWith("/playpause")) {
Map<String, Object> runningStatus = getRunningStatus();
- ApplicationSupport applicationSupport = getCurrentApplicationSupport(runningStatus, pianobarSupport);
+ ApplicationSupport applicationSupport = getCurrentApplicationSupport(runningStatus, musicPlayer);
if (applicationSupport != null) {
applicationSupport.playPause();
}
@@ -64,7 +64,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse response) throw
} else if (pathInfo.startsWith("/next")) {
Map<String, Object> runningStatus = getRunningStatus();
- ApplicationSupport applicationSupport = getCurrentApplicationSupport(runningStatus, pianobarSupport);
+ ApplicationSupport applicationSupport = getCurrentApplicationSupport(runningStatus, musicPlayer);
if (applicationSupport != null) {
applicationSupport.next();
}
@@ -72,14 +72,14 @@ protected void doGet(HttpServletRequest req, HttpServletResponse response) throw
} else if (pathInfo.startsWith("/previous")) {
Map<String, Object> runningStatus = getRunningStatus();
- ApplicationSupport applicationSupport = getCurrentApplicationSupport(runningStatus, pianobarSupport);
+ ApplicationSupport applicationSupport = getCurrentApplicationSupport(runningStatus, musicPlayer);
if (applicationSupport != null) {
applicationSupport.previous();
}
appendRunningStatus(response, runningStatus);
} else if (pathInfo.startsWith("/thumbsup")) {
Map<String, Object> runningStatus = getRunningStatus();
- ApplicationSupport applicationSupport = getCurrentApplicationSupport(runningStatus, pianobarSupport);
+ ApplicationSupport applicationSupport = getCurrentApplicationSupport(runningStatus, musicPlayer);
if (applicationSupport != null) {
applicationSupport.thumbsUp();
}
@@ -87,7 +87,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse response) throw
} else if (pathInfo.startsWith("/thumbsdown")) {
Map<String, Object> runningStatus = getRunningStatus();
- ApplicationSupport applicationSupport = getCurrentApplicationSupport(runningStatus, pianobarSupport);
+ ApplicationSupport applicationSupport = getCurrentApplicationSupport(runningStatus, musicPlayer);
if (applicationSupport != null) {
applicationSupport.thumbsDown();
}
View
27 src/com/sleazyweasel/applescriptifier/GuiMain.scala
@@ -30,32 +30,31 @@ class GuiMain extends MuseControllerMain {
macApp.setDefaultMenuBar(menubar.peer)
}
- private def createPandoraMenuItem(preferences: MuseControllerPreferences, pianobarSupport: MusicPlayer, menubar: MenuBar): MenuItem = {
+ private def createPandoraMenuItem(preferences: MuseControllerPreferences, pandoraPlayer: MusicPlayer, menubar: MenuBar, playerSupplier: MusicPlayerSupplier): MenuItem = {
val pandoraMenuItem = new MenuItem("Pandora")
pandoraMenuItem.enabled = preferences.isPianoBarEnabled
pandoraMenuItem.reactions += {
- case ButtonClicked(`pandoraMenuItem`) => startupPandora(pandoraMenuItem, pianobarSupport, preferences, menubar)
+ case ButtonClicked(`pandoraMenuItem`) => startupPandora(pandoraMenuItem, pandoraPlayer, preferences, menubar, playerSupplier)
}
pandoraMenuItem
}
- private def createSpotifyMenuItem(preferences: MuseControllerPreferences, spotifySupport: NativeSpotifySupportImpl, menubar: MenuBar): MenuItem = {
+ private def createSpotifyMenuItem(preferences: MuseControllerPreferences, spotifySupport: NativeSpotifySupport, menubar: MenuBar, playerSupplier: MusicPlayerSupplier): MenuItem = {
val spotifyMenuItem = new MenuItem("Spotify")
spotifyMenuItem.enabled = true
spotifyMenuItem.reactions += {
- case ButtonClicked(`spotifyMenuItem`) => startupSpotify(spotifyMenuItem, spotifySupport, preferences, menubar)
+ case ButtonClicked(`spotifyMenuItem`) => startupSpotify(spotifyMenuItem, spotifySupport, preferences, menubar, playerSupplier)
}
spotifyMenuItem
}
- def startupGui(musicPlayer: MusicPlayer, preferences: MuseControllerPreferences) {
- val spotifySupport = new NativeSpotifySupportImpl
+ def startupGui(playerSupplier: MusicPlayerSupplier, preferences: MuseControllerPreferences, spotifyPlayer: NativeSpotifySupport, pandoraPlayer: MusicPlayer) {
Swing.onEDT({
val menubar = new MenuBar
- val pandoraMenuItem = createPandoraMenuItem(preferences, musicPlayer, menubar)
- val spotifyMenuItem = createSpotifyMenuItem(preferences, spotifySupport, menubar)
+ val pandoraMenuItem = createPandoraMenuItem(preferences, pandoraPlayer, menubar, playerSupplier)
+ val spotifyMenuItem = createSpotifyMenuItem(preferences, spotifyPlayer, menubar, playerSupplier)
val menu = new Menu("Music")
menu.contents += pandoraMenuItem
@@ -65,10 +64,10 @@ class GuiMain extends MuseControllerMain {
setUpMacApplicationState(preferences, menubar)
if (preferences.isPianoBarEnabled && preferences.wasPandoraTheLastStreamerOpen) {
- startupPandora(pandoraMenuItem, musicPlayer, preferences, menubar)
+ startupPandora(pandoraMenuItem, pandoraPlayer, preferences, menubar, playerSupplier)
}
else if (preferences.isSpotifyEnabled && preferences.wasSpotifyTheLastStreamerOpen) {
- startupSpotify(spotifyMenuItem, spotifySupport, preferences, menubar)
+ startupSpotify(spotifyMenuItem, spotifyPlayer, preferences, menubar, playerSupplier)
}
else {
new Frame pack()
@@ -76,8 +75,9 @@ class GuiMain extends MuseControllerMain {
})
}
- private def startupSpotify(spotifyMenuItem: MenuItem, spotifySupport: NativeSpotifySupport, preferences: MuseControllerPreferences, mainMenuBar: MenuBar) {
- if (spotifySupport.isSpotifyAuthorized) {
+ private def startupSpotify(spotifyMenuItem: MenuItem, spotifySupport: NativeSpotifySupport, preferences: MuseControllerPreferences, mainMenuBar: MenuBar, playerSupplier: MusicPlayerSupplier) {
+ playerSupplier.setCurrentApplication(Application.SPOTIFY)
+ if (spotifySupport.isAuthorized) {
setActiveFrame(null)
val spotifyUI = new SpotifyUI(spotifySupport, mainMenuBar.peer, spotifyMenuItem.peer, preferences)
val window = spotifyUI.getWindow
@@ -99,8 +99,9 @@ class GuiMain extends MuseControllerMain {
window.setVisible(true)
}
- private def startupPandora(pandoraMenuItem: MenuItem, musicPlayer: MusicPlayer, preferences: MuseControllerPreferences, mainMenuBar: MenuBar) {
+ private def startupPandora(pandoraMenuItem: MenuItem, musicPlayer: MusicPlayer, preferences: MuseControllerPreferences, mainMenuBar: MenuBar, playerSupplier: MusicPlayerSupplier) {
setActiveFrame(null)
+ playerSupplier.setCurrentApplication(Application.PANDORAONE)
if (musicPlayer.isConfigured) {
try {
val pianobarUI = new PandoraUI(musicPlayer, mainMenuBar.peer, pandoraMenuItem.peer, preferences)
View
11 src/com/sleazyweasel/applescriptifier/JavaPandoraPlayer.java
@@ -190,6 +190,7 @@ public MusicPlayerState getState() {
artist = song.getArtist();
album = song.getAlbum();
albumArtUrl = song.getAlbumCoverUrl();
+ System.out.println("albumArtUrl = " + albumArtUrl);
detailUrl = song.getAlbumDetailURL();
//todo figure out how to get total track time.
currentTimeInTrack = formatCurrentTime();
@@ -348,6 +349,11 @@ public boolean isConfigured() {
}
@Override
+ public boolean isAuthorized() {
+ return isConfigured();
+ }
+
+ @Override
public boolean isPlaying() {
return player.getStatus() == BasicPlayer.PLAYING;
}
@@ -362,6 +368,11 @@ public void addListener(MusicPlayerStateChangeListener listener) {
}
@Override
+ public void removeListener(MusicPlayerStateChangeListener listener) {
+ listeners.remove(listener);
+ }
+
+ @Override
public void cancelStationSelection() {
currentInputType = MusicPlayerInputType.NONE;
}
View
8 src/com/sleazyweasel/applescriptifier/MusicPlayer.java
@@ -32,9 +32,13 @@
void initializeFromSavedUserState(MuseControllerPreferences preferences);
+ void removeListener(MusicPlayerStateChangeListener listener);
+
+ boolean isConfigured();
+
+ boolean isAuthorized();
+
public interface MusicPlayerStateChangeListener {
void stateChanged(MusicPlayer player, MusicPlayerState state);
}
-
- public boolean isConfigured();
}
View
14 src/com/sleazyweasel/applescriptifier/MusicPlayerServlet.java
@@ -13,12 +13,12 @@
import java.util.concurrent.atomic.AtomicReference;
public class MusicPlayerServlet extends HttpServlet {
- private final MusicPlayer musicPlayer;
+ private final MusicPlayerSupplier musicPlayer;
private AtomicReference<MusicPlayerState> musicPlayerState = new AtomicReference<MusicPlayerState>(new MusicPlayerState(false, "", "", "", "", MusicPlayerInputType.NONE, new HashMap<Integer, String>(), "", "", false, "", 1.0));
- public MusicPlayerServlet(MusicPlayer musicPlayer) {
- this.musicPlayer = musicPlayer;
+ public MusicPlayerServlet(MusicPlayerSupplier players) {
+ this.musicPlayer = players;
}
public void init() {
@@ -103,7 +103,7 @@ protected void doGet(HttpServletRequest req, HttpServletResponse response) throw
String stationId = req.getParameter("id");
musicPlayer.selectStation(Integer.valueOf(stationId));
} else if (pathInfo.startsWith("/albumArt")) {
- populateResponseDataFromFile(new HashMap<String, Object>());
+ populateResponseDataFromMusicPlayerState(new HashMap<String, Object>());
Map<String, String> responseData = new HashMap<String, String>(1);
responseData.put("albumArtUrl", musicPlayerState.get().getAlbumArtUrl());
@@ -119,11 +119,11 @@ private void appendStatus(HttpServletResponse response) throws IOException {
}
private void appendStatus(HttpServletResponse response, Map<String, Object> responseData) throws IOException {
- populateResponseDataFromFile(responseData);
+ populateResponseDataFromMusicPlayerState(responseData);
response.getWriter().append(new Gson().toJson(responseData));
}
- private void populateResponseDataFromFile(Map<String, Object> responseData) {
+ private void populateResponseDataFromMusicPlayerState(Map<String, Object> responseData) {
musicPlayer.activate();
MusicPlayerState state = musicPlayerState.get();
@@ -152,7 +152,7 @@ private void sleep() {
}
// private void sendTextCommand(String command) {
-// musicPlayer.sendTextCommand(command);
+// playerSupplier.sendTextCommand(command);
// }
}
View
135 src/com/sleazyweasel/applescriptifier/MusicPlayerSupplier.java
@@ -0,0 +1,135 @@
+package com.sleazyweasel.applescriptifier;
+
+import com.sleazyweasel.applescriptifier.preferences.MuseControllerPreferences;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class MusicPlayerSupplier implements MusicPlayer {
+ private final Map<Application, MusicPlayer> suppliers = new HashMap<Application, MusicPlayer>();
+ private final List<MusicPlayerStateChangeListener> listeners = new ArrayList<MusicPlayerStateChangeListener>();
+ private Application currentApplication;
+
+ public void addMusicPlayer(Application application, MusicPlayer musicPlayer) {
+ suppliers.put(application, musicPlayer);
+ }
+
+ public void setCurrentApplication(Application currentApplication) {
+ MusicPlayer oldPlayer = getCurrentMusicPlayer();
+ if (oldPlayer != null) {
+ for (MusicPlayerStateChangeListener listener : listeners) {
+ oldPlayer.removeListener(listener);
+ }
+ }
+ this.currentApplication = currentApplication;
+ MusicPlayer newPlayer = getCurrentMusicPlayer();
+ if (newPlayer != null) {
+ for (MusicPlayerStateChangeListener listener : listeners) {
+ newPlayer.addListener(listener);
+ }
+ }
+ }
+
+ @Override
+ public void removeListener(MusicPlayerStateChangeListener listener) {
+ listeners.remove(listener);
+ MusicPlayer currentMusicPlayer = getCurrentMusicPlayer();
+ if (currentMusicPlayer != null) {
+ currentMusicPlayer.removeListener(listener);
+ }
+ }
+
+ @Override
+ public void addListener(MusicPlayer.MusicPlayerStateChangeListener listener) {
+ listeners.add(listener);
+ MusicPlayer currentMusicPlayer = getCurrentMusicPlayer();
+ if (currentMusicPlayer != null) {
+ currentMusicPlayer.addListener(listener);
+ }
+ }
+
+ private MusicPlayer getCurrentMusicPlayer() {
+ return suppliers.get(currentApplication);
+ }
+
+ public void volumeUp() {
+ getCurrentMusicPlayer().volumeUp();
+ }
+
+ public void bounce() {
+ getCurrentMusicPlayer().bounce();
+ }
+
+ public void thumbsDown() {
+ getCurrentMusicPlayer().thumbsDown();
+ }
+
+ public void next() {
+ getCurrentMusicPlayer().next();
+ }
+
+ public void playPause() {
+ getCurrentMusicPlayer().playPause();
+ }
+
+ public boolean isConfigured() {
+ return getCurrentMusicPlayer().isConfigured();
+ }
+
+ @Override
+ public boolean isAuthorized() {
+ return getCurrentMusicPlayer().isAuthorized();
+ }
+
+ public boolean isPlaying() {
+ return getCurrentMusicPlayer().isPlaying();
+ }
+
+ public void initializeFromSavedUserState(MuseControllerPreferences preferences) {
+ getCurrentMusicPlayer().initializeFromSavedUserState(preferences);
+ }
+
+ public void activate() {
+ getCurrentMusicPlayer().activate();
+ }
+
+ public void askToChooseStation() {
+ getCurrentMusicPlayer().askToChooseStation();
+ }
+
+ public void close() {
+ getCurrentMusicPlayer().close();
+ }
+
+ public void cancelStationSelection() {
+ getCurrentMusicPlayer().cancelStationSelection();
+ }
+
+ public MusicPlayerState getState() {
+ return getCurrentMusicPlayer().getState();
+ }
+
+ public void selectStation(Integer stationNumber) {
+ getCurrentMusicPlayer().selectStation(stationNumber);
+ }
+
+ public void volumeDown() {
+ getCurrentMusicPlayer().volumeDown();
+ }
+
+ public void saveConfig(String username, char[] password) throws IOException {
+ getCurrentMusicPlayer().saveConfig(username, password);
+ }
+
+ public void thumbsUp() {
+ getCurrentMusicPlayer().thumbsUp();
+ }
+
+ public void previous() {
+ getCurrentMusicPlayer().previous();
+ }
+
+}
View
33 src/com/sleazyweasel/applescriptifier/NativeSpotifySupportImpl.java
@@ -248,6 +248,11 @@ public void initializeFromSavedUserState(MuseControllerPreferences preferences)
}
@Override
+ public void removeListener(MusicPlayerStateChangeListener listener) {
+ listeners.remove(listener);
+ }
+
+ @Override
public void playPause() {
if (Status.PLAY.equals(playerStatus)) {
pause();
@@ -277,18 +282,33 @@ public Image image(String imageCode) {
@Override
public void bounce() {
- throw new UnsupportedOperationException();
+ //no op for now...
}
@Override
public void activate() {
- throw new UnsupportedOperationException();
+ //no op?
}
@Override
public MusicPlayerState getState() {
- return new MusicPlayerState(false, currentTrack.getTitle(), currentTrack.getArtist().getName(), currentPlaylist.getName(), currentTrack.getAlbum().getName(), currentInputType,
- buildStationMap(), currentTrack.getCover(), renderCurrentPosition(), isPlaying(), null, volume);
+ String title = "";
+ String artistName = "";
+ String albumName = "";
+ String cover = "";
+ if (currentTrack != null) {
+ title = currentTrack.getTitle();
+ artistName = currentTrack.getArtist().getName();
+ albumName = currentTrack.getAlbum().getName();
+ //todo this is not a URL that anyone can use to get the image... figure out how to get an image URL from spotify, if it is even possible.
+ cover = currentTrack.getCover();
+ }
+ String playlistName = "";
+ if (currentPlaylist != null) {
+ playlistName = currentPlaylist.getName();
+ }
+ return new MusicPlayerState(false, title, artistName, playlistName, albumName, currentInputType,
+ buildStationMap(), cover, renderCurrentPosition(), isPlaying(), null, volume);
}
private String renderCurrentPosition() {
@@ -331,6 +351,11 @@ public boolean isConfigured() {
return getConfigFile().exists();
}
+ @Override
+ public boolean isAuthorized() {
+ return isSpotifyAuthorized();
+ }
+
private void notifyListeners() {
for (MusicPlayerStateChangeListener listener : listeners) {
listener.stateChanged(this, getState());
View
28 src/com/sleazyweasel/applescriptifier/ScalaMain.scala
@@ -39,16 +39,30 @@ class ScalaMain {
private final val PORT: Int = 23233
private val preferences: MuseControllerPreferences = new MuseControllerPreferences(Preferences.userNodeForPackage(classOf[ScalaMain]))
- private val musicPlayer: MusicPlayer = new JavaPandoraPlayer(preferences)
private def start() {
println("start")
val main = new GuiMain()
activateSparkle()
- main.startupGui(musicPlayer, preferences)
+ val playerSupplier: MusicPlayerSupplier = new MusicPlayerSupplier
+ val spotifyPlayer: NativeSpotifySupportImpl = new NativeSpotifySupportImpl
+ val pandoraPlayer: JavaPandoraPlayer = new JavaPandoraPlayer(preferences)
+
+ playerSupplier.addMusicPlayer(Application.SPOTIFY, spotifyPlayer)
+ playerSupplier.addMusicPlayer(Application.PANDORAONE, pandoraPlayer)
+ if (preferences.wasPandoraTheLastStreamerOpen()) {
+ playerSupplier.setCurrentApplication(Application.PANDORAONE)
+ }
+ else if (preferences.wasSpotifyTheLastStreamerOpen()) {
+ playerSupplier.setCurrentApplication(Application.SPOTIFY)
+ }
+ else if (preferences.isPianoBarEnabled) {
+ playerSupplier.setCurrentApplication(Application.PANDORAONE)
+ }
+ main.startupGui(playerSupplier, preferences, spotifyPlayer, pandoraPlayer)
if (preferences.isMuseControlEnabled) {
- startupWebServer(musicPlayer)
+ startupWebServer(playerSupplier)
}
}
@@ -63,7 +77,7 @@ class ScalaMain {
}
}
- private def startupWebServer(pianobarSupport: MusicPlayer) {
+ private def startupWebServer(players: MusicPlayerSupplier) {
//big todo: make the port dynamic...search until you find a free one.
val server = new Server(PORT)
register(0, 0, InetAddress.getLocalHost.getHostName, "_asrunner._udp", "local.", null, PORT, null, new RegisterListener {
@@ -79,16 +93,16 @@ class ScalaMain {
context.setContextPath("/")
server.setHandler(context)
- val airfoilServlet = new AirfoilServlet(pianobarSupport)
+ val airfoilServlet = new AirfoilServlet(players)
context.addServlet(new ServletHolder(airfoilServlet), "/airfoil/*")
context.addServlet(new ServletHolder(new PandoraBoyServlet), "/pandoraboy/*")
context.addServlet(new ServletHolder(new PulsarServlet), "/pulsar/*")
context.addServlet(new ServletHolder(new RdioServlet), "/rdio/*")
- val nativePianobarServlet = new MusicPlayerServlet(pianobarSupport)
+ val nativePianobarServlet = new MusicPlayerServlet(players)
context.addServlet(new ServletHolder(nativePianobarServlet), "/pianobar/*")
context.addServlet(new ServletHolder(new SpotifyServlet), "/spotify/*")
- context.addServlet(new ServletHolder(new ControlServlet(musicPlayer)), "/control/*")
+ context.addServlet(new ServletHolder(new ControlServlet(players)), "/control/*")
spawn({
server.start();
View
39 test/com/sleazyweasel/applescriptifier/MusicPlayerSupplierTest.java
@@ -0,0 +1,39 @@
+package com.sleazyweasel.applescriptifier;
+
+import org.junit.Test;
+
+import static org.mockito.Mockito.*;
+
+public class MusicPlayerSupplierTest {
+
+ @Test
+ public void testListeners() throws Exception {
+
+ MusicPlayer rdioPlayer = mock(MusicPlayer.class);
+ MusicPlayer pandoraPlayer = mock(MusicPlayer.class);
+ MusicPlayer.MusicPlayerStateChangeListener listener = mock(MusicPlayer.MusicPlayerStateChangeListener.class);
+
+ MusicPlayerSupplier testClass = new MusicPlayerSupplier();
+ testClass.addMusicPlayer(Application.RDIO, rdioPlayer);
+ testClass.addMusicPlayer(Application.PANDORABOY, pandoraPlayer);
+
+ testClass.setCurrentApplication(Application.RDIO);
+ verify(rdioPlayer, never()).addListener(any(MusicPlayer.MusicPlayerStateChangeListener.class));
+ verify(pandoraPlayer, never()).addListener(any(MusicPlayer.MusicPlayerStateChangeListener.class));
+
+ testClass.addListener(listener);
+ verify(rdioPlayer).addListener(listener);
+
+ testClass.setCurrentApplication(Application.PANDORABOY);
+ verify(rdioPlayer).removeListener(listener);
+ verify(pandoraPlayer).addListener(listener);
+
+ testClass.setCurrentApplication(Application.RDIO);
+ verify(pandoraPlayer).removeListener(listener);
+ verify(rdioPlayer, times(2)).addListener(listener);
+
+ testClass.removeListener(listener);
+ verify(rdioPlayer, times(2)).removeListener(listener);
+ }
+
+}

No commit comments for this range

Something went wrong with that request. Please try again.