1 /* ncmpc (Ncurses MPD Client)
2 * (c) 2004-2010 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 mpdclient_put_connection(c);
63 return false;
64 }
66 static void
67 schedule_seek_timer(struct mpdclient *c)
68 {
69 assert(seek_source_id == 0);
71 seek_source_id = g_timeout_add(500, seek_timer, c);
72 }
74 void
75 cancel_seek_timer(void)
76 {
77 if (seek_source_id != 0) {
78 g_source_remove(seek_source_id);
79 seek_source_id = 0;
80 }
81 }
83 static bool
84 setup_seek(struct mpdclient *c)
85 {
86 if (!mpdclient_is_playing(c))
87 return false;
89 if (seek_id != (int)mpd_status_get_song_id(c->status)) {
90 seek_id = mpd_status_get_song_id(c->status);
91 seek_target_time = mpd_status_get_elapsed_time(c->status);
92 }
94 schedule_seek_timer(c);
96 return true;
97 }
99 bool
100 handle_player_command(struct mpdclient *c, command_t cmd)
101 {
102 if (!mpdclient_is_connected(c) || c->status == NULL)
103 return false;
105 cancel_seek_timer();
107 switch(cmd) {
108 struct mpd_connection *connection;
110 /*
111 case CMD_PLAY:
112 mpdclient_cmd_play(c, MPD_PLAY_AT_BEGINNING);
113 break;
114 */
115 case CMD_PAUSE:
116 connection = mpdclient_get_connection(c);
117 if (connection == NULL)
118 break;
120 if (!mpd_run_pause(connection,
121 mpd_status_get_state(c->status) != MPD_STATE_PAUSE))
122 mpdclient_handle_error(c);
123 break;
124 case CMD_STOP:
125 connection = mpdclient_get_connection(c);
126 if (connection == NULL)
127 break;
129 if (!mpd_run_stop(connection))
130 mpdclient_handle_error(c);
131 break;
132 case CMD_CROP:
133 mpdclient_cmd_crop(c);
134 break;
135 case CMD_SEEK_FORWARD:
136 if (!setup_seek(c))
137 break;
139 seek_target_time += options.seek_time;
140 if (seek_target_time > (int)mpd_status_get_total_time(c->status))
141 seek_target_time = mpd_status_get_total_time(c->status);
142 break;
144 case CMD_TRACK_NEXT:
145 connection = mpdclient_get_connection(c);
146 if (connection == NULL)
147 break;
149 if (!mpd_run_next(connection))
150 mpdclient_handle_error(c);
151 break;
152 case CMD_SEEK_BACKWARD:
153 if (!setup_seek(c))
154 break;
156 seek_target_time -= options.seek_time;
157 if (seek_target_time < 0)
158 seek_target_time = 0;
159 break;
161 case CMD_TRACK_PREVIOUS:
162 connection = mpdclient_get_connection(c);
163 if (connection == NULL)
164 break;
166 if (!mpd_run_previous(connection))
167 mpdclient_handle_error(c);
168 break;
169 case CMD_SHUFFLE:
170 connection = mpdclient_get_connection(c);
171 if (connection == NULL)
172 break;
174 if (mpd_run_shuffle(connection))
175 screen_status_message(_("Shuffled queue"));
176 else
177 mpdclient_handle_error(c);
178 break;
179 case CMD_CLEAR:
180 connection = mpdclient_get_connection(c);
181 if (connection == NULL)
182 break;
184 if (mpdclient_cmd_clear(c))
185 screen_status_message(_("Cleared queue"));
186 break;
187 case CMD_REPEAT:
188 connection = mpdclient_get_connection(c);
189 if (connection == NULL)
190 break;
192 if (!mpd_run_repeat(connection,
193 !mpd_status_get_repeat(c->status)))
194 mpdclient_handle_error(c);
195 break;
196 case CMD_RANDOM:
197 connection = mpdclient_get_connection(c);
198 if (connection == NULL)
199 break;
201 if (!mpd_run_random(connection,
202 !mpd_status_get_random(c->status)))
203 mpdclient_handle_error(c);
204 break;
205 case CMD_SINGLE:
206 connection = mpdclient_get_connection(c);
207 if (connection == NULL)
208 break;
210 if (!mpd_run_single(connection,
211 !mpd_status_get_single(c->status)))
212 mpdclient_handle_error(c);
213 break;
214 case CMD_CONSUME:
215 connection = mpdclient_get_connection(c);
216 if (connection == NULL)
217 break;
219 if (!mpd_run_consume(connection,
220 !mpd_status_get_consume(c->status)))
221 mpdclient_handle_error(c);
222 break;
223 case CMD_CROSSFADE:
224 connection = mpdclient_get_connection(c);
225 if (connection == NULL)
226 break;
228 if (!mpd_run_crossfade(connection,
229 mpd_status_get_crossfade(c->status) > 0
230 ? 0 : options.crossfade_time))
231 mpdclient_handle_error(c);
232 break;
233 case CMD_DB_UPDATE:
234 screen_database_update(c, NULL);
235 break;
236 case CMD_VOLUME_UP:
237 mpdclient_cmd_volume_up(c);
238 break;
239 case CMD_VOLUME_DOWN:
240 mpdclient_cmd_volume_down(c);
241 break;
243 default:
244 return false;
245 }
247 return true;
248 }