Code

release v0.29
[ncmpc.git] / src / player_command.c
index 29967957ab0e364db7284b49b26211cfa9131ba2..1a06bfabcb1b9b1bf465f883b9a02fd927bffba4 100644 (file)
@@ -1,17 +1,17 @@
 /* ncmpc (Ncurses MPD Client)
- * (c) 2004-2009 The Music Player Daemon Project
+ * (c) 2004-2017 The Music Player Daemon Project
  * Project homepage: http://musicpd.org
-
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
-
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
-
+ *
  * You should have received a copy of the GNU General Public License along
  * with this program; if not, write to the Free Software Foundation, Inc.,
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 #include "player_command.h"
 #include "mpdclient.h"
 #include "options.h"
-#include "screen.h"
 #include "i18n.h"
-
-#define IS_PLAYING(s) (s==MPD_STATE_PLAY)
-#define IS_PAUSED(s) (s==MPD_STATE_PAUSE)
-#define IS_STOPPED(s) (!(IS_PLAYING(s) | IS_PAUSED(s)))
+#include "screen_client.h"
+#include "screen_status.h"
 
 int seek_id = -1;
-int seek_target_time = 0;
+int seek_target_time;
+
+static guint seek_source_id;
+
+static void
+commit_seek(struct mpdclient *c)
+{
+       if (seek_id < 0)
+               return;
+
+       struct mpd_connection *connection = mpdclient_get_connection(c);
+       if (connection == NULL) {
+               seek_id = -1;
+               return;
+       }
+
+       if (c->song != NULL && (unsigned)seek_id == mpd_song_get_id(c->song))
+               if (!mpd_run_seek_id(connection, seek_id, seek_target_time))
+                       mpdclient_handle_error(c);
+
+       seek_id = -1;
+}
+
+/**
+ * This timer is invoked after seeking when the user hasn't typed a
+ * key for 500ms.  It is used to do the real seeking.
+ */
+static gboolean
+seek_timer(gpointer data)
+{
+       struct mpdclient *c = data;
+
+       seek_source_id = 0;
+       commit_seek(c);
+       return false;
+}
 
-int
+static void
+schedule_seek_timer(struct mpdclient *c)
+{
+       assert(seek_source_id == 0);
+
+       seek_source_id = g_timeout_add(500, seek_timer, c);
+}
+
+void
+cancel_seek_timer(void)
+{
+       if (seek_source_id != 0) {
+               g_source_remove(seek_source_id);
+               seek_source_id = 0;
+       }
+}
+
+static bool
+setup_seek(struct mpdclient *c)
+{
+       if (!mpdclient_is_playing(c))
+               return false;
+
+       if (seek_id != (int)mpd_status_get_song_id(c->status)) {
+               seek_id = mpd_status_get_song_id(c->status);
+               seek_target_time = mpd_status_get_elapsed_time(c->status);
+       }
+
+       schedule_seek_timer(c);
+
+       return true;
+}
+
+bool
 handle_player_command(struct mpdclient *c, command_t cmd)
 {
-       if (c->connection == NULL || c->status == NULL)
-               return 0;
+       if (!mpdclient_is_connected(c) || c->status == NULL)
+               return false;
+
+       cancel_seek_timer();
 
        switch(cmd) {
+               struct mpd_connection *connection;
+
                /*
        case CMD_PLAY:
                mpdclient_cmd_play(c, MPD_PLAY_AT_BEGINNING);
                break;
                */
        case CMD_PAUSE:
-               mpdclient_cmd_pause(c, !IS_PAUSED(mpd_status_get_state(c->status)));
+               connection = mpdclient_get_connection(c);
+               if (connection == NULL)
+                       break;
+
+               if (!mpd_run_pause(connection,
+                                  mpd_status_get_state(c->status) != MPD_STATE_PAUSE))
+                       mpdclient_handle_error(c);
                break;
        case CMD_STOP:
-               mpdclient_cmd_stop(c);
+               connection = mpdclient_get_connection(c);
+               if (connection == NULL)
+                       break;
+
+               if (!mpd_run_stop(connection))
+                       mpdclient_handle_error(c);
                break;
        case CMD_CROP:
                mpdclient_cmd_crop(c);
                break;
        case CMD_SEEK_FORWARD:
-               if (!IS_STOPPED(mpd_status_get_state(c->status))) {
-                       if (c->song != NULL &&
-                           seek_id != (int)mpd_song_get_id(c->song)) {
-                               seek_id = mpd_song_get_id(c->song);
-                               seek_target_time = mpd_status_get_elapsed_time(c->status);
-                       }
-                       seek_target_time+=options.seek_time;
-                       if (seek_target_time < (int)mpd_status_get_total_time(c->status))
-                               break;
+               if (!setup_seek(c))
+                       break;
+
+               seek_target_time += options.seek_time;
+               if (seek_target_time > (int)mpd_status_get_total_time(c->status))
                        seek_target_time = mpd_status_get_total_time(c->status);
-                       /* seek_target_time=0; */
-               }
                break;
-               /* fall through... */
+
        case CMD_TRACK_NEXT:
-               if (!IS_STOPPED(mpd_status_get_state(c->status)))
-                       mpdclient_cmd_next(c);
+               connection = mpdclient_get_connection(c);
+               if (connection == NULL)
+                       break;
+
+               if (!mpd_run_next(connection))
+                       mpdclient_handle_error(c);
                break;
        case CMD_SEEK_BACKWARD:
-               if (!IS_STOPPED(mpd_status_get_state(c->status))) {
-                       if (seek_id != (int)mpd_song_get_id(c->song)) {
-                               seek_id = mpd_song_get_id(c->song);
-                               seek_target_time = mpd_status_get_elapsed_time(c->status);
-                       }
-                       seek_target_time-=options.seek_time;
-                       if (seek_target_time < 0)
-                               seek_target_time=0;
-               }
+               if (!setup_seek(c))
+                       break;
+
+               seek_target_time -= options.seek_time;
+               if (seek_target_time < 0)
+                       seek_target_time = 0;
                break;
+
        case CMD_TRACK_PREVIOUS:
-               if (!IS_STOPPED(mpd_status_get_state(c->status)))
-                       mpdclient_cmd_prev(c);
+               connection = mpdclient_get_connection(c);
+               if (connection == NULL)
+                       break;
+
+               if (!mpd_run_previous(connection))
+                       mpdclient_handle_error(c);
                break;
        case CMD_SHUFFLE:
-               if (mpdclient_cmd_shuffle(c) == 0)
-                       screen_status_message(_("Shuffled playlist"));
+               connection = mpdclient_get_connection(c);
+               if (connection == NULL)
+                       break;
+
+               if (mpd_run_shuffle(connection))
+                       screen_status_message(_("Shuffled queue"));
+               else
+                       mpdclient_handle_error(c);
                break;
        case CMD_CLEAR:
-               if (mpdclient_cmd_clear(c) == 0)
-                       screen_status_message(_("Cleared playlist"));
+               connection = mpdclient_get_connection(c);
+               if (connection == NULL)
+                       break;
+
+               if (mpdclient_cmd_clear(c))
+                       screen_status_message(_("Cleared queue"));
                break;
        case CMD_REPEAT:
-               mpdclient_cmd_repeat(c, !mpd_status_get_repeat(c->status));
+               connection = mpdclient_get_connection(c);
+               if (connection == NULL)
+                       break;
+
+               if (!mpd_run_repeat(connection,
+                                   !mpd_status_get_repeat(c->status)))
+                       mpdclient_handle_error(c);
                break;
        case CMD_RANDOM:
-               mpdclient_cmd_random(c, !mpd_status_get_random(c->status));
+               connection = mpdclient_get_connection(c);
+               if (connection == NULL)
+                       break;
+
+               if (!mpd_run_random(connection,
+                                   !mpd_status_get_random(c->status)))
+                       mpdclient_handle_error(c);
                break;
        case CMD_SINGLE:
-               mpdclient_cmd_single(c, !mpd_status_get_single(c->status));
+               connection = mpdclient_get_connection(c);
+               if (connection == NULL)
+                       break;
+
+               if (!mpd_run_single(connection,
+                                   !mpd_status_get_single(c->status)))
+                       mpdclient_handle_error(c);
                break;
        case CMD_CONSUME:
-               mpdclient_cmd_consume(c, !mpd_status_get_consume(c->status));
+               connection = mpdclient_get_connection(c);
+               if (connection == NULL)
+                       break;
+
+               if (!mpd_run_consume(connection,
+                                    !mpd_status_get_consume(c->status)))
+                       mpdclient_handle_error(c);
                break;
        case CMD_CROSSFADE:
-               if (mpd_status_get_crossfade(c->status))
-                       mpdclient_cmd_crossfade(c, 0);
-               else
-                       mpdclient_cmd_crossfade(c, options.crossfade_time);
+               connection = mpdclient_get_connection(c);
+               if (connection == NULL)
+                       break;
+
+               if (!mpd_run_crossfade(connection,
+                                      mpd_status_get_crossfade(c->status) > 0
+                                      ? 0 : options.crossfade_time))
+                       mpdclient_handle_error(c);
                break;
        case CMD_DB_UPDATE:
-               if (!mpd_status_get_update_id(c->status)) {
-                       if( mpdclient_cmd_db_update(c,NULL)==0 )
-                               screen_status_printf(_("Database update started"));
-               } else
-                       screen_status_printf(_("Database update running..."));
+               screen_database_update(c, NULL);
                break;
        case CMD_VOLUME_UP:
                mpdclient_cmd_volume_up(c);
@@ -126,8 +240,8 @@ handle_player_command(struct mpdclient *c, command_t cmd)
                break;
 
        default:
-               return 0;
+               return false;
        }
 
-       return 1;
+       return true;
 }