]> git.basschouten.com Git - openhab-addons.git/blob
b118a2392c68c45de0bcdd381e6007d3242e865e
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.spotify.internal.handler;
14
15 import static org.openhab.binding.spotify.internal.SpotifyBindingConstants.*;
16
17 import java.util.Collections;
18 import java.util.List;
19
20 import org.eclipse.jdt.annotation.NonNullByDefault;
21 import org.openhab.binding.spotify.internal.api.SpotifyApi;
22 import org.openhab.binding.spotify.internal.api.model.Device;
23 import org.openhab.binding.spotify.internal.api.model.Playlist;
24 import org.openhab.core.library.types.DecimalType;
25 import org.openhab.core.library.types.NextPreviousType;
26 import org.openhab.core.library.types.OnOffType;
27 import org.openhab.core.library.types.PercentType;
28 import org.openhab.core.library.types.PlayPauseType;
29 import org.openhab.core.library.types.StringType;
30 import org.openhab.core.thing.ChannelUID;
31 import org.openhab.core.types.Command;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 /**
36  * Class to handle {@link Command} actions and call the Spotify Web Api.
37  *
38  * @author Andreas Stenlund - Initial contribution
39  * @author Hilbrand Bouwkamp - Moved to separate class, general refactoring and bug fixes
40  */
41 @NonNullByDefault
42 class SpotifyHandleCommands {
43
44     private final Logger logger = LoggerFactory.getLogger(SpotifyHandleCommands.class);
45
46     private final SpotifyApi spotifyApi;
47
48     private List<Device> devices = Collections.emptyList();
49     private List<Playlist> playlists = Collections.emptyList();
50
51     /**
52      * Constructor. For the bridge the deviceId is empty.
53      *
54      * @param spotifyApi The api class to use to call the spotify api
55      */
56     public SpotifyHandleCommands(SpotifyApi spotifyApi) {
57         this.spotifyApi = spotifyApi;
58     }
59
60     public void setDevices(final List<Device> devices) {
61         this.devices = devices;
62     }
63
64     public void setPlaylists(final List<Playlist> playlists) {
65         this.playlists = playlists;
66     }
67
68     /**
69      * Handles commands from the given Channel and calls Spotify Web Api with the given command.
70      *
71      * @param channelUID Channel the command is from
72      * @param command command to run
73      * @param active true if current known device is the active device
74      * @param deviceId Current known active Spotify device id
75      * @return true if the command was done or else if no channel or command matched
76      */
77     public boolean handleCommand(ChannelUID channelUID, Command command, boolean active, String deviceId) {
78         logger.debug("Received channel: {}, command: {}", channelUID, command);
79         boolean commandRun = false;
80         final String channel = channelUID.getId();
81
82         switch (channel) {
83             case CHANNEL_DEVICENAME:
84                 if (command instanceof StringType) {
85                     final String newName = command.toString();
86
87                     devices.stream().filter(d -> d.getName().equals(newName)).findFirst()
88                             .ifPresent(d -> playDeviceId(d.getId(), active, deviceId));
89                     commandRun = true;
90                 }
91                 break;
92             case CHANNEL_DEVICEID:
93             case CHANNEL_DEVICES:
94                 if (command instanceof StringType) {
95                     playDeviceId(command.toString(), active, deviceId);
96                     commandRun = true;
97                 }
98                 break;
99             case CHANNEL_DEVICEPLAYER:
100             case CHANNEL_TRACKPLAYER:
101                 commandRun = handleDevicePlay(command, active, deviceId);
102                 break;
103             case CHANNEL_DEVICESHUFFLE:
104                 if (command instanceof OnOffType onOffCommand) {
105                     spotifyApi.setShuffleState(deviceId, onOffCommand);
106                     commandRun = true;
107                 }
108                 break;
109             case CHANNEL_TRACKREPEAT:
110                 if (command instanceof StringType) {
111                     spotifyApi.setRepeatState(deviceId, command.toString());
112                     commandRun = true;
113                 }
114             case CHANNEL_DEVICEVOLUME:
115                 if (command instanceof DecimalType decimalCommand) {
116                     final PercentType volume = command instanceof PercentType percentType ? percentType
117                             : new PercentType(decimalCommand.intValue());
118
119                     spotifyApi.setVolume(deviceId, volume.intValue());
120                     commandRun = true;
121                 }
122                 break;
123             case CHANNEL_TRACKPLAY:
124             case CHANNEL_PLAYLISTS:
125                 if (command instanceof StringType) {
126                     spotifyApi.playTrack(deviceId, command.toString(), 0, 0);
127                     commandRun = true;
128                 }
129                 break;
130             case CHANNEL_PLAYLISTNAME:
131                 if (command instanceof StringType) {
132                     final String newName = command.toString();
133
134                     playlists.stream().filter(pl -> pl.getName().equals(newName)).findFirst()
135                             .ifPresent(pl -> spotifyApi.playTrack(deviceId, pl.getUri(), 0, 0));
136                     commandRun = true;
137                 }
138                 break;
139         }
140         return commandRun;
141     }
142
143     private void playDeviceId(String newDeviceId, boolean active, String currentDeviceId) {
144         if (currentDeviceId.equals(newDeviceId) && active) {
145             spotifyApi.play(newDeviceId);
146         } else {
147             spotifyApi.transferPlay(newDeviceId, true);
148         }
149     }
150
151     /**
152      * Helper method to handle device play status.
153      *
154      * @param command command to run
155      * @param active true if the device this command is send to is the active device
156      * @param deviceId Spotify device id the command is intended for
157      * @return true if the command was done or else if no channel or command matched
158      */
159     private boolean handleDevicePlay(Command command, boolean active, String deviceId) {
160         if (command instanceof PlayPauseType) {
161             final boolean play = command == PlayPauseType.PLAY;
162
163             if (active || deviceId.isEmpty()) {
164                 if (play) {
165                     spotifyApi.play(deviceId);
166                 } else {
167                     spotifyApi.pause(deviceId);
168                 }
169             } else {
170                 spotifyApi.transferPlay(deviceId, play);
171             }
172             return true;
173         } else if (command instanceof NextPreviousType) {
174             if (command == NextPreviousType.NEXT) {
175                 spotifyApi.next(deviceId);
176             } else {
177                 spotifyApi.previous(deviceId);
178             }
179             return true;
180         }
181         return false;
182     }
183 }