Code

screen: moved screen_interface externs to each screen header
[ncmpc.git] / src / screen_play.c
index 6872b139110b9e9741001351d7d0a1842e3868bb..ceb13616662197b076a0316e9fdfbb3dc735a971 100644 (file)
@@ -17,6 +17,9 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */
 
+#include "screen_play.h"
+#include "screen_interface.h"
+#include "screen_file.h"
 #include "config.h"
 #include "i18n.h"
 #include "charset.h"
 #include "utils.h"
 #include "strfsong.h"
 #include "wreadln.h"
-#include "command.h"
 #include "colors.h"
 #include "screen.h"
 #include "screen_utils.h"
-#include "screen_play.h"
+#include "screen_song.h"
+#include "screen_lyrics.h"
 
 #ifndef NCMPC_MINI
 #include "hscroll.h"
@@ -38,9 +41,7 @@
 #include <mpd/client.h>
 
 #include <ctype.h>
-#include <stdlib.h>
 #include <string.h>
-#include <time.h>
 #include <glib.h>
 
 #define MAX_SONG_LENGTH 512
@@ -58,6 +59,7 @@ static bool must_scroll;
 
 static struct mpdclient_playlist *playlist;
 static int current_song_id = -1;
+static int selected_song_id = -1;
 static list_window_t *lw = NULL;
 static guint timer_hide_cursor_id;
 
@@ -71,33 +73,45 @@ playlist_repaint(void)
        wrefresh(lw->w);
 }
 
+static const struct mpd_song *
+playlist_selected_song(void)
+{
+       return !lw->range_selection &&
+               lw->selected < playlist_length(playlist)
+               ? playlist_get(playlist, lw->selected)
+               : NULL;
+}
+
 static void
-playlist_repaint_if_active(void)
+playlist_save_selection(void)
 {
-       if (screen_is_visible(&screen_playlist))
-               playlist_repaint();
+       selected_song_id = playlist_selected_song() != NULL
+               ? (int)mpd_song_get_id(playlist_selected_song())
+               : -1;
 }
 
 static void
-playlist_changed_callback(struct mpdclient *c, int event, gpointer data)
+playlist_restore_selection(void)
 {
-       switch (event) {
-       case PLAYLIST_EVENT_DELETE:
-               break;
-       case PLAYLIST_EVENT_MOVE:
-               if(lw->range_selection < 0)
-               {
-                       lw->selected = *((int *) data);
-                       if (lw->selected < lw->start)
-                               lw->start--;
-               }
-               break;
-       default:
-               break;
-       }
+       const struct mpd_song *song;
+       int pos;
 
-       list_window_check_selected(lw, c->playlist.list->len);
-       playlist_repaint_if_active();
+       if (selected_song_id < 0)
+               /* there was no selection */
+               return;
+
+       song = playlist_selected_song();
+       if (song != NULL &&
+           mpd_song_get_id(song) == (unsigned)selected_song_id)
+               /* selection is still valid */
+               return;
+
+       pos = playlist_get_index_from_id(playlist, selected_song_id);
+       if (pos >= 0)
+               lw->selected = pos;
+
+       list_window_check_selected(lw, playlist_length(playlist));
+       playlist_save_selection();
 }
 
 #ifndef NCMPC_MINI
@@ -168,11 +182,12 @@ list_callback(unsigned idx, bool *highlight, char **second_column, G_GNUC_UNUSED
 static void
 center_playing_item(struct mpdclient *c, bool center_cursor)
 {
+       const struct mpd_song *song;
        unsigned length = c->playlist.list->len;
        int idx;
 
-       if (!c->song || c->status == NULL ||
-           IS_STOPPED(mpd_status_get_state(c->status)))
+       song = mpdclient_get_current_song(c);
+       if (song == NULL)
                return;
 
        /* try to center the song that are playing */
@@ -286,8 +301,7 @@ playlist_save(struct mpdclient *c, char *name, char *defaultname)
 
 
                /* query the user for a filename */
-               filename = screen_readln(screen.status_window.w,
-                                        _("Save playlist as"),
+               filename = screen_readln(_("Save playlist as"),
                                         defaultname,
                                         NULL,
                                         gcmp);
@@ -311,7 +325,6 @@ playlist_save(struct mpdclient *c, char *name, char *defaultname)
 
        filename_utf8 = locale_to_utf8(filename);
        error = mpdclient_cmd_save_playlist(c, filename_utf8);
-       g_free(filename_utf8);
 
        if (error) {
                gint code = GET_ACK_ERROR_CODE(error);
@@ -322,32 +335,38 @@ playlist_save(struct mpdclient *c, char *name, char *defaultname)
 
                        buf = g_strdup_printf(_("Replace %s [%s/%s] ? "),
                                              filename, YES, NO);
-                       key = tolower(screen_getch(screen.status_window.w,
-                                                  buf));
+                       key = tolower(screen_getch(buf));
                        g_free(buf);
 
-                       if (key == YES[0]) {
-                               filename_utf8 = locale_to_utf8(filename);
-                               error = mpdclient_cmd_delete_playlist(c, filename_utf8);
+                       if (key != YES[0]) {
                                g_free(filename_utf8);
+                               g_free(filename);
+                               screen_status_printf(_("Aborted"));
+                               return -1;
+                       }
 
-                               if (error) {
-                                       g_free(filename);
-                                       return -1;
-                               }
+                       error = mpdclient_cmd_delete_playlist(c, filename_utf8);
+                       if (error) {
+                               g_free(filename_utf8);
+                               g_free(filename);
+                               return -1;
+                       }
 
-                               error = playlist_save(c, filename, NULL);
+                       error = mpdclient_cmd_save_playlist(c, filename_utf8);
+                       if (error) {
+                               g_free(filename_utf8);
                                g_free(filename);
                                return error;
                        }
-
-                       screen_status_printf(_("Aborted"));
+               } else {
+                       g_free(filename_utf8);
+                       g_free(filename);
+                       return -1;
                }
-
-               g_free(filename);
-               return -1;
        }
 
+       g_free(filename_utf8);
+
        /* success */
        screen_status_printf(_("Saved %s"), filename);
        g_free(filename);
@@ -424,8 +443,7 @@ handle_add_to_playlist(struct mpdclient *c)
 #endif
 
        /* get path */
-       path = screen_readln(screen.status_window.w,
-                            _("Add"),
+       path = screen_readln(_("Add"),
                             NULL,
                             NULL,
 #ifdef NCMPC_MINI
@@ -488,8 +506,6 @@ timer_hide_cursor(gpointer data)
 static void
 play_open(struct mpdclient *c)
 {
-       static gboolean install_cb = TRUE;
-
        playlist = &c->playlist;
 
        assert(timer_hide_cursor_id == 0);
@@ -499,10 +515,7 @@ play_open(struct mpdclient *c)
                                                     timer_hide_cursor, c);
        }
 
-       if (install_cb) {
-               mpdclient_install_playlist_callback(c, playlist_changed_callback);
-               install_cb = FALSE;
-       }
+       playlist_restore_selection();
 }
 
 static void
@@ -553,9 +566,12 @@ play_update(struct mpdclient *c)
 {
        static int prev_song_id = -1;
 
-       current_song_id = c->song != NULL && c->status != NULL &&
+       if (c->events & MPD_IDLE_PLAYLIST)
+               playlist_restore_selection();
+
+       current_song_id = c->status != NULL &&
                !IS_STOPPED(mpd_status_get_state(c->status))
-               ? (int)mpd_song_get_id(c->song) : -1;
+               ? (int)mpd_status_get_song_id(c->status) : -1;
 
        if (current_song_id != prev_song_id) {
                prev_song_id = current_song_id;
@@ -571,6 +587,10 @@ play_update(struct mpdclient *c)
                   enabled */
                playlist_repaint();
 #endif
+       } else if (c->events & MPD_IDLE_PLAYLIST) {
+               /* the playlist has changed, we must paint the new
+                  version */
+               playlist_repaint();
        }
 }
 
@@ -608,6 +628,7 @@ handle_mouse_event(struct mpdclient *c)
 
        lw->selected = selected;
        list_window_check_selected(lw, playlist_length(playlist));
+       playlist_save_selection();
        playlist_repaint();
 
        return true;
@@ -631,6 +652,7 @@ play_cmd(struct mpdclient *c, command_t cmd)
        }
 
        if (list_window_cmd(lw, playlist_length(&c->playlist), cmd)) {
+               playlist_save_selection();
                playlist_repaint();
                return true;
        }
@@ -640,21 +662,17 @@ play_cmd(struct mpdclient *c, command_t cmd)
                mpdclient_cmd_play(c, lw->selected);
                return true;
        case CMD_DELETE:
-       {
-               int i = lw->selected_end, start = lw->selected_start;
-               for(; i >= start; --i)
-                       mpdclient_cmd_delete(c, i);
-
-               i++;
-               if(i >= (int)playlist_length(&c->playlist))
-                       i--;
-               lw->selected = i;
-               lw->selected_start = i;
-               lw->selected_end = i;
-               lw->range_selection = false;
+               if (lw->range_selection) {
+                       mpdclient_cmd_delete_range(c, lw->selected_start,
+                                                  lw->selected_end + 1);
+               } else {
+                       mpdclient_cmd_delete(c, lw->selected);
+               }
 
+               lw->selected = lw->selected_end = lw->selected_start;
+               lw->range_selection = false;
                return true;
-       }
+
        case CMD_SAVE_PLAYLIST:
                playlist_save(c, NULL, NULL);
                return true;
@@ -668,6 +686,7 @@ play_cmd(struct mpdclient *c, command_t cmd)
        case CMD_SELECT_PLAYING:
                list_window_set_selected(lw, playlist_get_index(&c->playlist,
                                                                c->song));
+               playlist_save_selection();
                return true;
        case CMD_SHUFFLE:
        {
@@ -701,6 +720,8 @@ play_cmd(struct mpdclient *c, command_t cmd)
                        lw->selected_start--;
                        lw->selected_end--;
                }
+
+               playlist_save_selection();
                return true;
        case CMD_LIST_MOVE_DOWN:
                if(lw->selected_end+1 >= playlist_length(&c->playlist))
@@ -723,6 +744,8 @@ play_cmd(struct mpdclient *c, command_t cmd)
                        lw->selected_start++;
                        lw->selected_end++;
                }
+
+               playlist_save_selection();
                return true;
        case CMD_LIST_FIND:
        case CMD_LIST_RFIND:
@@ -730,10 +753,12 @@ play_cmd(struct mpdclient *c, command_t cmd)
        case CMD_LIST_RFIND_NEXT:
                screen_find(lw, playlist_length(&c->playlist),
                            cmd, list_callback, NULL);
+               playlist_save_selection();
                playlist_repaint();
                return true;
        case CMD_LIST_JUMP:
                screen_jump(lw, list_callback, NULL);
+               playlist_save_selection();
                playlist_repaint();
                return true;
 
@@ -744,8 +769,8 @@ play_cmd(struct mpdclient *c, command_t cmd)
 
 #ifdef ENABLE_SONG_SCREEN
        case CMD_SCREEN_SONG:
-               if (lw->selected < playlist_length(&c->playlist)) {
-                       screen_song_switch(c, playlist_get(&c->playlist, lw->selected));
+               if (playlist_selected_song()) {
+                       screen_song_switch(c, playlist_selected_song());
                        return true;
                }
 
@@ -753,8 +778,8 @@ play_cmd(struct mpdclient *c, command_t cmd)
 #endif
 
        case CMD_LOCATE:
-               if (lw->selected < playlist_length(&c->playlist)) {
-                       screen_file_goto_song(c, playlist_get(&c->playlist, lw->selected));
+               if (playlist_selected_song()) {
+                       screen_file_goto_song(c, playlist_selected_song());
                        return true;
                }