Compare commits
3 Commits
6298235e22
...
2cd100af7a
Author | SHA1 | Date | |
---|---|---|---|
2cd100af7a | |||
44ebc3591e | |||
0691c533b4 |
128
nncmpp.c
128
nncmpp.c
@ -1366,7 +1366,6 @@ app_write_mpd_status (struct row_buffer *buf)
|
|||||||
bool single = (s = str_map_find (map, "single")) && strcmp (s, "0");
|
bool single = (s = str_map_find (map, "single")) && strcmp (s, "0");
|
||||||
bool consume = (s = str_map_find (map, "consume")) && strcmp (s, "0");
|
bool consume = (s = str_map_find (map, "consume")) && strcmp (s, "0");
|
||||||
|
|
||||||
// TODO: remove the conditionals once we make them clickable
|
|
||||||
struct row_buffer right = row_buffer_make ();
|
struct row_buffer right = row_buffer_make ();
|
||||||
chtype a[2] = { APP_ATTR (NORMAL), APP_ATTR (HIGHLIGHT) };
|
chtype a[2] = { APP_ATTR (NORMAL), APP_ATTR (HIGHLIGHT) };
|
||||||
if (repeat) row_buffer_append_args (&right,
|
if (repeat) row_buffer_append_args (&right,
|
||||||
@ -2209,52 +2208,65 @@ current_tab_on_item_draw (size_t item_index, struct row_buffer *buffer,
|
|||||||
free (s);
|
free (s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
current_tab_move_song (const char *id, int diff)
|
mpd_on_move_response (const struct mpd_response *response,
|
||||||
|
const struct strv *data, void *user_data)
|
||||||
{
|
{
|
||||||
struct mpd_client *c = &g.client;
|
(void) data;
|
||||||
int target = g_current_tab.item_selected + diff;
|
|
||||||
if (c->state != MPD_CONNECTED || target < 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
char *target_str = xstrdup_printf ("%d", target);
|
*(bool *) user_data = false;
|
||||||
mpd_client_send_command (c, "moveid", id, target_str, NULL);
|
if (!response->success)
|
||||||
free (target_str);
|
print_error ("%s: %s", "command failed", response->message_text);
|
||||||
// TODO: we should create a cancellable action waiting for the move to
|
|
||||||
// finish, so that holding Shift-arrows works as expected.
|
|
||||||
mpd_client_add_task (c, mpd_on_simple_response, NULL);
|
|
||||||
mpd_client_idle (c, 0);
|
|
||||||
|
|
||||||
// XXX: this behaves a bit erratically, as even if we waited for
|
|
||||||
// a confirmation from the daemon, it would precede the playlist update
|
|
||||||
g_current_tab.item_selected = target;
|
|
||||||
app_move_selection (0);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
current_tab_on_action (enum action action)
|
current_tab_move_selection (int diff)
|
||||||
{
|
{
|
||||||
struct tab *self = g.active_tab;
|
static bool already_moving;
|
||||||
struct tab_range range = tab_selection_range (self);
|
if (already_moving)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// TODO: handle multiselect properly
|
||||||
|
struct tab *self = &g_current_tab;
|
||||||
|
struct mpd_client *c = &g.client;
|
||||||
compact_map_t map = item_list_get (&g.playlist, self->item_selected);
|
compact_map_t map = item_list_get (&g.playlist, self->item_selected);
|
||||||
|
|
||||||
const char *id;
|
const char *id;
|
||||||
if (!map || !(id = compact_map_find (map, "id")))
|
if (!map || !(id = compact_map_find (map, "id")))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
int target = self->item_selected + diff;
|
||||||
|
if (c->state != MPD_CONNECTED || target < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
char *target_str = xstrdup_printf ("%d", target);
|
||||||
|
mpd_client_send_command (c, "moveid", id, target_str, NULL);
|
||||||
|
free (target_str);
|
||||||
|
mpd_client_add_task (c, mpd_on_move_response, &already_moving);
|
||||||
|
mpd_client_idle (c, 0);
|
||||||
|
|
||||||
|
return already_moving = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
current_tab_on_action (enum action action)
|
||||||
|
{
|
||||||
|
struct tab *self = &g_current_tab;
|
||||||
|
compact_map_t map = item_list_get (&g.playlist, self->item_selected);
|
||||||
switch (action)
|
switch (action)
|
||||||
{
|
{
|
||||||
// TODO: make this block more than just multiselect-tolerant
|
const char *id;
|
||||||
case ACTION_MOVE_UP: return current_tab_move_song (id, -1);
|
case ACTION_MOVE_UP:
|
||||||
case ACTION_MOVE_DOWN: return current_tab_move_song (id, 1);
|
return current_tab_move_selection (-1);
|
||||||
|
case ACTION_MOVE_DOWN:
|
||||||
|
return current_tab_move_selection (+1);
|
||||||
case ACTION_CHOOSE:
|
case ACTION_CHOOSE:
|
||||||
return MPD_SIMPLE ("playid", id);
|
return map && (id = compact_map_find (map, "id"))
|
||||||
|
&& MPD_SIMPLE ("playid", id);
|
||||||
case ACTION_DELETE:
|
case ACTION_DELETE:
|
||||||
{
|
{
|
||||||
struct mpd_client *c = &g.client;
|
struct mpd_client *c = &g.client;
|
||||||
|
struct tab_range range = tab_selection_range (self);
|
||||||
if (range.from < 0 || c->state != MPD_CONNECTED)
|
if (range.from < 0 || c->state != MPD_CONNECTED)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -2271,15 +2283,16 @@ current_tab_on_action (enum action action)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
current_tab_update (void)
|
current_tab_update (void)
|
||||||
{
|
{
|
||||||
g_current_tab.item_count = g.playlist.len;
|
g_current_tab.item_count = g.playlist.len;
|
||||||
|
g_current_tab.item_mark =
|
||||||
|
MIN ((int) g.playlist.len - 1, g_current_tab.item_mark);
|
||||||
app_invalidate ();
|
app_invalidate ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3364,7 +3377,7 @@ mpd_update_playback_state (void)
|
|||||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mpd_process_info (const struct strv *data)
|
mpd_process_info_data (const struct strv *data)
|
||||||
{
|
{
|
||||||
struct str_map *map = &g.playback_info;
|
struct str_map *map = &g.playback_info;
|
||||||
|
|
||||||
@ -3398,6 +3411,57 @@ mpd_process_info (const struct strv *data)
|
|||||||
str_map_free (&item);
|
str_map_free (&item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Find a song by its id in the current playlist. Expensive, rarely called.
|
||||||
|
static ssize_t
|
||||||
|
mpd_find_pos_of_id (const char *desired_id)
|
||||||
|
{
|
||||||
|
compact_map_t map;
|
||||||
|
const char *id;
|
||||||
|
for (size_t i = 0; i < g.playlist.len; i++)
|
||||||
|
{
|
||||||
|
if ((map = item_list_get (&g.playlist, i))
|
||||||
|
&& (id = compact_map_find (map, "id"))
|
||||||
|
&& !strcmp (id, desired_id))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
mpd_id_of_pos (int pos)
|
||||||
|
{
|
||||||
|
compact_map_t map = item_list_get (&g.playlist, pos);
|
||||||
|
return map ? compact_map_find (map, "id") : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
mpd_process_info (const struct strv *data)
|
||||||
|
{
|
||||||
|
int *selected = &g_current_tab.item_selected;
|
||||||
|
int *marked = &g_current_tab.item_mark;
|
||||||
|
char *prev_sel_id = mpd_id_of_pos (*selected);
|
||||||
|
char *prev_mark_id = mpd_id_of_pos (*marked);
|
||||||
|
if (prev_sel_id) prev_sel_id = xstrdup (prev_sel_id);
|
||||||
|
if (prev_mark_id) prev_mark_id = xstrdup (prev_mark_id);
|
||||||
|
|
||||||
|
mpd_process_info_data (data);
|
||||||
|
|
||||||
|
const char *sel_id = mpd_id_of_pos (*selected);
|
||||||
|
const char *mark_id = mpd_id_of_pos (*marked);
|
||||||
|
|
||||||
|
if (prev_mark_id && (!mark_id || strcmp (prev_mark_id, mark_id)))
|
||||||
|
*marked = mpd_find_pos_of_id (prev_mark_id);
|
||||||
|
if (prev_sel_id && (!sel_id || strcmp (prev_sel_id, sel_id)))
|
||||||
|
{
|
||||||
|
if ((*selected = mpd_find_pos_of_id (prev_sel_id)) < 0)
|
||||||
|
*marked = -1;
|
||||||
|
app_move_selection (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
free (prev_sel_id);
|
||||||
|
free (prev_mark_id);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mpd_on_info_response (const struct mpd_response *response,
|
mpd_on_info_response (const struct mpd_response *response,
|
||||||
const struct strv *data, void *user_data)
|
const struct strv *data, void *user_data)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user