/**
* Copyright (c) 2010-2016 by the respective copyright holders.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.openhab.binding.squeezebox.internal;
import java.util.ArrayList;
import java.util.List;
import org.openhab.binding.squeezebox.SqueezeboxBindingConfig;
import org.openhab.binding.squeezebox.SqueezeboxBindingProvider;
import org.openhab.core.binding.AbstractBinding;
import org.openhab.core.library.types.DecimalType;
import org.openhab.core.library.types.IncreaseDecreaseType;
import org.openhab.core.library.types.OnOffType;
import org.openhab.core.library.types.PercentType;
import org.openhab.core.library.types.StringType;
import org.openhab.core.library.types.UpDownType;
import org.openhab.core.types.Command;
import org.openhab.io.squeezeserver.SqueezePlayer.PlayerEvent;
import org.openhab.io.squeezeserver.SqueezePlayerEventListener;
import org.openhab.io.squeezeserver.SqueezeServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Binding which communicates with (one or many) Squeezeboxes.
*
* @author Markus Wolters
* @author Ben Jones
* @since 1.3.0
*/
public class SqueezeboxBinding extends AbstractBinding<SqueezeboxBindingProvider>implements SqueezePlayerEventListener {
private static final Logger logger = LoggerFactory.getLogger(SqueezeboxBinding.class);
private SqueezeServer squeezeServer;
/**
* @{inheritDoc}
*/
@Override
public void internalReceiveCommand(String itemName, Command command) {
if (squeezeServer == null) {
logger.warn("Squeeze Server not initialised or configured yet, ignoring command '{}' for item '{}'",
command.toString(), itemName);
return;
}
logger.trace("internalReceiveCommand(itemname = {}, command = {})", itemName, command.toString());
for (SqueezeboxBindingProvider provider : providers) {
SqueezeboxBindingConfig bindingConfig = provider.getSqueezeboxBindingConfig(itemName);
String playerId = bindingConfig.getPlayerId();
try {
switch (bindingConfig.getCommandType()) {
case POWER:
if (command.equals(OnOffType.ON)) {
squeezeServer.powerOn(playerId);
} else if (command.equals(OnOffType.OFF)) {
squeezeServer.powerOff(playerId);
}
break;
case MUTE:
if (command.equals(OnOffType.ON)) {
squeezeServer.mute(playerId);
} else if (command.equals(OnOffType.OFF)) {
squeezeServer.unMute(playerId);
}
break;
case VOLUME:
if (command.equals(IncreaseDecreaseType.INCREASE)) {
squeezeServer.volumeUp(playerId);
} else if (command.equals(IncreaseDecreaseType.DECREASE)) {
squeezeServer.volumeDown(playerId);
} else if (command.equals(UpDownType.UP)) {
squeezeServer.volumeUp(playerId);
} else if (command.equals(UpDownType.DOWN)) {
squeezeServer.volumeDown(playerId);
} else if (command instanceof DecimalType) {
squeezeServer.setVolume(playerId, ((DecimalType) command).intValue());
}
break;
case PLAY:
if (command.equals(OnOffType.ON)) {
squeezeServer.play(playerId);
} else if (command.equals(OnOffType.OFF)) {
squeezeServer.stop(playerId);
}
break;
case PAUSE:
if (command.equals(OnOffType.ON)) {
squeezeServer.pause(playerId);
} else if (command.equals(OnOffType.OFF)) {
squeezeServer.unPause(playerId);
}
break;
case STOP:
if (command.equals(OnOffType.ON)) {
squeezeServer.stop(playerId);
} else if (command.equals(OnOffType.OFF)) {
squeezeServer.play(playerId);
}
break;
case NEXT:
if (command.equals(OnOffType.ON)) {
squeezeServer.next(playerId);
}
break;
case PREV:
if (command.equals(OnOffType.ON)) {
squeezeServer.prev(playerId);
}
break;
case HTTP:
if (command.equals(OnOffType.ON)) {
squeezeServer.playUrl(playerId, "http://" + bindingConfig.getExtra());
} else if (command.equals(OnOffType.OFF)) {
squeezeServer.stop(playerId);
}
break;
case FILE:
if (command.equals(OnOffType.ON)) {
squeezeServer.playUrl(playerId, "file://" + bindingConfig.getExtra());
} else if (command.equals(OnOffType.OFF)) {
squeezeServer.stop(playerId);
}
break;
case SYNC:
if (command.equals(OnOffType.ON)) {
squeezeServer.syncPlayer(playerId, bindingConfig.getExtra());
} else if (command.equals(OnOffType.OFF)) {
squeezeServer.unSyncPlayer(bindingConfig.getExtra());
}
break;
case COMMAND:
if (command instanceof StringType) {
squeezeServer.playerCommand(playerId, command.toString());
} else {
squeezeServer.playerCommand(playerId, bindingConfig.getExtra());
}
break;
default:
logger.warn("Unsupported command type '{}'", bindingConfig.getCommandType());
}
} catch (Exception e) {
logger.warn("Error executing command type '{}'", bindingConfig.getCommandType(), e);
}
}
}
@Override
public void powerChangeEvent(PlayerEvent event) {
booleanChangeEvent(event.getPlayerId(), CommandType.POWER, event.getPlayer().isPowered());
}
@Override
public void muteChangeEvent(PlayerEvent event) {
booleanChangeEvent(event.getPlayerId(), CommandType.MUTE, event.getPlayer().isMuted());
}
@Override
public void volumeChangeEvent(PlayerEvent event) {
percentChangeEvent(event.getPlayerId(), CommandType.VOLUME, event.getPlayer().getVolume());
}
@Override
public void currentPlaylistIndexEvent(PlayerEvent event) {
numberChangeEvent(event.getPlayerId(), CommandType.CURRTRACK, event.getPlayer().getCurrentPlaylistIndex());
}
@Override
public void currentPlayingTimeEvent(PlayerEvent event) {
numberChangeEvent(event.getPlayerId(), CommandType.PLAYTIME, event.getPlayer().getCurrentPlayingTime());
}
@Override
public void numberPlaylistTracksEvent(PlayerEvent event) {
numberChangeEvent(event.getPlayerId(), CommandType.NUMTRACKS, event.getPlayer().getNumberPlaylistTracks());
}
@Override
public void currentPlaylistShuffleEvent(PlayerEvent event) {
numberChangeEvent(event.getPlayerId(), CommandType.SHUFFLE, event.getPlayer().getCurrentPlaylistShuffle());
}
@Override
public void currentPlaylistRepeatEvent(PlayerEvent event) {
numberChangeEvent(event.getPlayerId(), CommandType.REPEAT, event.getPlayer().getCurrentPlaylistRepeat());
}
@Override
public void modeChangeEvent(PlayerEvent event) {
booleanChangeEvent(event.getPlayerId(), CommandType.PLAY, event.getPlayer().isPlaying());
booleanChangeEvent(event.getPlayerId(), CommandType.PAUSE, event.getPlayer().isPaused());
booleanChangeEvent(event.getPlayerId(), CommandType.STOP, event.getPlayer().isStopped());
}
@Override
public void titleChangeEvent(PlayerEvent event) {
stringChangeEvent(event.getPlayerId(), CommandType.TITLE, event.getPlayer().getTitle());
}
@Override
public void albumChangeEvent(PlayerEvent event) {
stringChangeEvent(event.getPlayerId(), CommandType.ALBUM, event.getPlayer().getAlbum());
}
@Override
public void artistChangeEvent(PlayerEvent event) {
stringChangeEvent(event.getPlayerId(), CommandType.ARTIST, event.getPlayer().getArtist());
}
@Override
public void coverArtChangeEvent(PlayerEvent event) {
stringChangeEvent(event.getPlayerId(), CommandType.COVERART, event.getPlayer().getCoverArt());
}
@Override
public void yearChangeEvent(PlayerEvent event) {
stringChangeEvent(event.getPlayerId(), CommandType.YEAR, Integer.toString(event.getPlayer().getYear()));
}
@Override
public void genreChangeEvent(PlayerEvent event) {
stringChangeEvent(event.getPlayerId(), CommandType.GENRE, event.getPlayer().getGenre());
}
@Override
public void remoteTitleChangeEvent(PlayerEvent event) {
stringChangeEvent(event.getPlayerId(), CommandType.REMOTETITLE, event.getPlayer().getRemoteTitle());
}
@Override
public void irCodeChangeEvent(PlayerEvent event) {
stringChangeEvent(event.getPlayerId(), CommandType.IRCODE, event.getPlayer().getIrCode());
}
private void stringChangeEvent(String playerId, CommandType commandType, String newState) {
logger.debug("SqueezePlayer {} -> {}: {}", playerId, commandType.getCommand(), newState);
for (String itemName : getItemNames(playerId, commandType)) {
eventPublisher.postUpdate(itemName, StringType.valueOf(newState));
}
}
private void percentChangeEvent(String playerId, CommandType commandType, int newState) {
logger.debug("SqueezePlayer {} -> {}: {}", playerId, commandType.getCommand(), newState);
for (String itemName : getItemNames(playerId, commandType)) {
eventPublisher.postUpdate(itemName, new PercentType(newState));
}
}
private void numberChangeEvent(String playerId, CommandType commandType, int newState) {
logger.debug("SqueezePlayer {} -> {}: {}", playerId, commandType.getCommand(), newState);
for (String itemName : getItemNames(playerId, commandType)) {
eventPublisher.postUpdate(itemName, new DecimalType(newState));
}
}
private void booleanChangeEvent(String playerId, CommandType commandType, boolean newState) {
logger.debug("SqueezePlayer {} -> {}: {}", playerId, commandType.getCommand(), newState);
for (String itemName : getItemNames(playerId, commandType)) {
if (newState) {
eventPublisher.postUpdate(itemName, OnOffType.ON);
} else {
eventPublisher.postUpdate(itemName, OnOffType.OFF);
}
}
}
private List<String> getItemNames(String playerId, CommandType commandType) {
List<String> itemNames = new ArrayList<String>();
for (SqueezeboxBindingProvider provider : this.providers) {
for (String itemName : provider.getItemNames()) {
SqueezeboxBindingConfig bindingConfig = provider.getSqueezeboxBindingConfig(itemName);
if (!bindingConfig.getPlayerId().equals(playerId)) {
continue;
}
if (!bindingConfig.getCommandType().equals(commandType)) {
continue;
}
itemNames.add(itemName);
}
}
return itemNames;
}
/**
* Setter for Declarative Services. Adds the SqueezeServer instance.
*
* @param squeezeServer
* Service.
*/
public void setSqueezeServer(SqueezeServer squeezeServer) {
this.squeezeServer = squeezeServer;
this.squeezeServer.addPlayerEventListener(this);
}
/**
* Unsetter for Declarative Services.
*
* @param squeezeServer
* Service to remove.
*/
public void unsetSqueezeServer(SqueezeServer squeezeServer) {
this.squeezeServer.removePlayerEventListener(this);
this.squeezeServer = null;
}
}