]> git.basschouten.com Git - openhab-addons.git/blob
61e7aa9da60fae71ef7c84640b548096968acfe0
[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.mpd.internal.protocol;
14
15 import org.eclipse.jdt.annotation.NonNullByDefault;
16 import org.eclipse.jdt.annotation.Nullable;
17 import org.openhab.binding.mpd.internal.handler.MPDEventListener;
18 import org.openhab.core.thing.ThingStatus;
19 import org.openhab.core.thing.ThingStatusDetail;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22
23 /**
24  * Class for communicating with the music player daemon through an IP connection
25  *
26  * @author Stefan Röllin - Initial contribution
27  */
28 @NonNullByDefault
29 public class MPDConnection implements MPDResponseListener {
30
31     private static final int DISPOSE_TIMEOUT_MS = 1000;
32
33     private final Logger logger = LoggerFactory.getLogger(MPDConnection.class);
34
35     private final MPDEventListener listener;
36
37     private @Nullable MPDConnectionThread connectionThread = null;
38
39     /**
40      * Constructor
41      *
42      * @param listener
43      */
44     public MPDConnection(MPDEventListener listener) {
45         this.listener = listener;
46     }
47
48     /**
49      * start the connection
50      *
51      * @param address the IP address of the music player daemon
52      * @param port the TCP port to be used
53      * @param password the password to connect to the music player daemon
54      * @param threadName the name of the thread
55      */
56     public void start(String address, Integer port, String password, String threadName) {
57         if (connectionThread == null) {
58             final MPDConnectionThread connectionThread = new MPDConnectionThread(this, address, port, password);
59             connectionThread.setName(threadName);
60             connectionThread.start();
61             this.connectionThread = connectionThread;
62         }
63     }
64
65     /**
66      * dispose the connection
67      */
68     public void dispose() {
69         final MPDConnectionThread connectionThread = this.connectionThread;
70         if (connectionThread != null) {
71             connectionThread.dispose();
72             connectionThread.interrupt();
73             try {
74                 connectionThread.join(DISPOSE_TIMEOUT_MS);
75             } catch (InterruptedException ignore) {
76             }
77             this.connectionThread = null;
78         }
79     }
80
81     /**
82      * send a command to the music player daemon
83      *
84      * @param command command to send
85      * @param parameter parameter of command
86      */
87     public void sendCommand(String command, String... parameter) {
88         addCommand(new MPDCommand(command, parameter));
89     }
90
91     /**
92      * play
93      */
94     public void play() {
95         sendCommand("play");
96     }
97
98     /**
99      * pause the music player daemon
100      */
101     public void pause() {
102         addCommand(new MPDCommand("pause", 1));
103     }
104
105     /**
106      * play next track
107      */
108     public void playNext() {
109         sendCommand("next");
110     }
111
112     /**
113      * play previous track
114      */
115     public void playPrevious() {
116         sendCommand("previous");
117     }
118
119     /**
120      * stop the music player daemon
121      */
122     public void stop() {
123         sendCommand("stop");
124     }
125
126     /**
127      * update status
128      */
129     public void updateStatus() {
130         sendCommand("status");
131     }
132
133     /**
134      * update information regarding current song
135      */
136     public void updateCurrentSong() {
137         sendCommand("currentsong");
138     }
139
140     /**
141      * set volume
142      *
143      * @param volume set new volume
144      */
145     public void setVolume(int volume) {
146         addCommand(new MPDCommand("setvol", volume));
147     }
148
149     private void addCommand(MPDCommand command) {
150         MPDConnectionThread connectionThread = this.connectionThread;
151         if (connectionThread != null) {
152             connectionThread.addCommand(command);
153         } else {
154             logger.debug("could not add command {} since thing offline", command.getCommand());
155         }
156     }
157
158     @Override
159     public void updateThingStatus(ThingStatus status, ThingStatusDetail statusDetail, @Nullable String cause) {
160         listener.updateThingStatus(status, statusDetail, cause);
161     }
162
163     @Override
164     public void onResponse(MPDResponse response) {
165         switch (response.getCommand()) {
166             case "idle":
167                 handleResponseIdle(response);
168                 break;
169             case "status":
170                 handleResponseStatus(response);
171                 break;
172             case "currentsong":
173                 handleResponseCurrentSong(response);
174                 break;
175             default:
176                 break;
177         }
178     }
179
180     private void handleResponseCurrentSong(MPDResponse response) {
181         MPDSong song = new MPDSong(response);
182         listener.updateMPDSong(song);
183     }
184
185     private void handleResponseIdle(MPDResponse response) {
186         boolean updateStatus = false;
187         boolean updateCurrentSong = false;
188         for (String line : response.getLines()) {
189             if (line.startsWith("changed:")) {
190                 line = line.substring(8).trim();
191                 switch (line) {
192                     case "player":
193                         updateStatus = true;
194                         updateCurrentSong = true;
195                         break;
196                     case "mixer":
197                         updateStatus = true;
198                         break;
199                     case "playlist":
200                         updateCurrentSong = true;
201                         break;
202                 }
203             }
204         }
205
206         if (updateStatus) {
207             updateStatus();
208         }
209         if (updateCurrentSong) {
210             updateCurrentSong();
211         }
212     }
213
214     private void handleResponseStatus(MPDResponse response) {
215         MPDStatus song = new MPDStatus(response);
216         listener.updateMPDStatus(song);
217     }
218 }