1 /* ncmpc (Ncurses MPD Client)
2 * (c) 2004-2017 The Music Player Daemon Project
3 * Project homepage: http://musicpd.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
20 #include "player_command.h"
21 #include "mpdclient.h"
22 #include "options.h"
23 #include "i18n.h"
24 #include "screen_client.h"
25 #include "screen_status.h"
27 int seek_id = -1;
28 int seek_target_time;
30 static guint seek_source_id;
32 static void
33 commit_seek(struct mpdclient *c)
34 {
35 if (seek_id < 0)
36 return;
38 struct mpd_connection *connection = mpdclient_get_connection(c);
39 if (connection == NULL) {
40 seek_id = -1;
41 return;
42 }
44 if (c->song != NULL && (unsigned)seek_id == mpd_song_get_id(c->song))
45 if (!mpd_run_seek_id(connection, seek_id, seek_target_time))
46 mpdclient_handle_error(c);
48 seek_id = -1;
49 }
51 /**
52 * This timer is invoked after seeking when the user hasn't typed a
53 * key for 500ms. It is used to do the real seeking.
54 */
55 static gboolean
56 seek_timer(gpointer data)
57 {
58 struct mpdclient *c = data;
60 seek_source_id = 0;
61 commit_seek(c);
62 return false;
63 }
65 static void
66 schedule_seek_timer(struct mpdclient *c)
67 {
68 assert(seek_source_id == 0);
70 seek_source_id = g_timeout_add(500, seek_timer, c);
71 }
73 void
74 cancel_seek_timer(void)
75 {
76 if (seek_source_id != 0) {
77 g_source_remove(seek_source_id);
78 seek_source_id = 0;
79 }
80 }
82 static bool
83 setup_seek(struct mpdclient *c)
84 {
85 if (!mpdclient_is_playing(c))
86 return false;
88 if (seek_id != (int)mpd_status_get_song_id(c->status)) {
89 seek_id = mpd_status_get_song_id(c->status);
90 seek_target_time = mpd_status_get_elapsed_time(c->status);
91 }
93 schedule_seek_timer(c);
95 return true;
96 }
98 bool
99 handle_player_command(struct mpdclient *c, command_t cmd)
100 {
101 if (!mpdclient_is_connected(c) || c->status == NULL)
102 return false;
104 cancel_seek_timer();
106 switch(cmd) {
107 struct mpd_connection *connection;
109 /*
110 case CMD_PLAY:
111 mpdclient_cmd_play(c, MPD_PLAY_AT_BEGINNING);
112 break;
113 */
114 case CMD_PAUSE:
115 connection = mpdclient_get_connection(c);
116 if (connection == NULL)
117 break;
119 if (!mpd_run_pause(connection,
120 mpd_status_get_state(c->status) != MPD_STATE_PAUSE))
121 mpdclient_handle_error(c);
122 break;
123 case CMD_STOP:
124 connection = mpdclient_get_connection(c);
125 if (connection == NULL)
126 break;
128 if (!mpd_run_stop(connection))
129 mpdclient_handle_error(c);
130 break;
131 case CMD_CROP:
132 mpdclient_cmd_crop(c);
133 break;
134 case CMD_SEEK_FORWARD:
135 if (!setup_seek(c))
136 break;
138 seek_target_time += options.seek_time;
139 if (seek_target_time > (int)mpd_status_get_total_time(c->status))
140 seek_target_time = mpd_status_get_total_time(c->status);
141 break;
143 case CMD_TRACK_NEXT:
144 connection = mpdclient_get_connection(c);
145 if (connection == NULL)
146 break;
148 if (!mpd_run_next(connection))
149 mpdclient_handle_error(c);
150 break;
151 case CMD_SEEK_BACKWARD:
152 if (!setup_seek(c))
153 break;
155 seek_target_time -= options.seek_time;
156 if (seek_target_time < 0)
157 seek_target_time = 0;
158 break;
160 case CMD_TRACK_PREVIOUS:
161 connection = mpdclient_get_connection(c);
162 if (connection == NULL)
163 break;
165 if (!mpd_run_previous(connection))
166 mpdclient_handle_error(c);
167 break;
168 case CMD_SHUFFLE:
169 connection = mpdclient_get_connection(c);
170 if (connection == NULL)
171 break;
173 if (mpd_run_shuffle(connection))
174 screen_status_message(_("Shuffled queue"));
175 else
176 mpdclient_handle_error(c);
177 break;
178 case CMD_CLEAR:
179 connection = mpdclient_get_connection(c);
180 if (connection == NULL)
181 break;
183 if (mpdclient_cmd_clear(c))
184 screen_status_message(_("Cleared queue"));
185 break;
186 case CMD_REPEAT:
187 connection = mpdclient_get_connection(c);
188 if (connection == NULL)
189 break;
191 if (!mpd_run_repeat(connection,
192 !mpd_status_get_repeat(c->status)))
193 mpdclient_handle_error(c);
194 break;
195 case CMD_RANDOM:
196 connection = mpdclient_get_connection(c);
197 if (connection == NULL)
198 break;
200 if (!mpd_run_random(connection,
201 !mpd_status_get_random(c->status)))
202 mpdclient_handle_error(c);
203 break;
204 case CMD_SINGLE:
205 connection = mpdclient_get_connection(c);
206 if (connection == NULL)
207 break;
209 if (!mpd_run_single(connection,
210 !mpd_status_get_single(c->status)))
211 mpdclient_handle_error(c);
212 break;
213 case CMD_CONSUME:
214 connection = mpdclient_get_connection(c);
215 if (connection == NULL)
216 break;
218 if (!mpd_run_consume(connection,
219 !mpd_status_get_consume(c->status)))
220 mpdclient_handle_error(c);
221 break;
222 case CMD_CROSSFADE:
223 connection = mpdclient_get_connection(c);
224 if (connection == NULL)
225 break;
227 if (!mpd_run_crossfade(connection,
228 mpd_status_get_crossfade(c->status) > 0
229 ? 0 : options.crossfade_time))
230 mpdclient_handle_error(c);
231 break;
232 case CMD_DB_UPDATE:
233 screen_database_update(c, NULL);
234 break;
235 case CMD_VOLUME_UP:
236 mpdclient_cmd_volume_up(c);
237 break;
238 case CMD_VOLUME_DOWN:
239 mpdclient_cmd_volume_down(c);
240 break;
242 default:
243 return false;
244 }
246 return true;
247 }