Compare commits
	
		
			2 Commits
		
	
	
		
			172ceffa9e
			...
			9a996c8440
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 9a996c8440 | |||
| a9d4f86493 | 
							
								
								
									
										2
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								NEWS
									
									
									
									
									
								
							| @ -6,6 +6,8 @@ Unreleased | |||||||
| 
 | 
 | ||||||
|  * Added a "z" binding to center the view on the selected item |  * Added a "z" binding to center the view on the selected item | ||||||
| 
 | 
 | ||||||
|  |  * Added a "?" binding to describe items in various tabs | ||||||
|  | 
 | ||||||
|  * Made it possible to adjust the spectrum analyzer's FPS limit |  * Made it possible to adjust the spectrum analyzer's FPS limit | ||||||
| 
 | 
 | ||||||
|  * Fixed possibility of connection timeouts with PulseAudio integration |  * Fixed possibility of connection timeouts with PulseAudio integration | ||||||
|  | |||||||
| @ -36,6 +36,7 @@ PULSE_MUTE,         Toggle PulseAudio sink mute | |||||||
| 
 | 
 | ||||||
| CHOOSE,             Choose item | CHOOSE,             Choose item | ||||||
| DELETE,             Delete item | DELETE,             Delete item | ||||||
|  | DESCRIBE,           Describe item | ||||||
| UP,                 Go up a level | UP,                 Go up a level | ||||||
| MULTISELECT,        Toggle multiselect | MULTISELECT,        Toggle multiselect | ||||||
| INCREMENTAL_SEARCH, Incremental search | INCREMENTAL_SEARCH, Incremental search | ||||||
|  | |||||||
							
								
								
									
										117
									
								
								nncmpp.c
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								nncmpp.c
									
									
									
									
									
								
							| @ -1298,6 +1298,7 @@ static struct app_context | |||||||
| 
 | 
 | ||||||
| 	struct poller_timer message_timer;  ///< Message timeout
 | 	struct poller_timer message_timer;  ///< Message timeout
 | ||||||
| 	char *message;                      ///< Message to show in the statusbar
 | 	char *message;                      ///< Message to show in the statusbar
 | ||||||
|  | 	char *message_detail;               ///< Non-emphasized part
 | ||||||
| 
 | 
 | ||||||
| 	// Connection:
 | 	// Connection:
 | ||||||
| 
 | 
 | ||||||
| @ -1700,6 +1701,7 @@ app_free_context (void) | |||||||
| 	poller_curl_free (&g.poller_curl); | 	poller_curl_free (&g.poller_curl); | ||||||
| 	poller_free (&g.poller); | 	poller_free (&g.poller); | ||||||
| 	free (g.message); | 	free (g.message); | ||||||
|  | 	free (g.message_detail); | ||||||
| 
 | 
 | ||||||
| 	if (g.tk) | 	if (g.tk) | ||||||
| 		termo_destroy (g.tk); | 		termo_destroy (g.tk); | ||||||
| @ -2239,21 +2241,28 @@ static void | |||||||
| app_layout_statusbar (void) | app_layout_statusbar (void) | ||||||
| { | { | ||||||
| 	struct layout l = {}; | 	struct layout l = {}; | ||||||
|  | 	chtype attrs[2] = { APP_ATTR (NORMAL), APP_ATTR (HIGHLIGHT) }; | ||||||
| 	if (g.message) | 	if (g.message) | ||||||
| 	{ | 	{ | ||||||
| 		app_push (&l, g.ui->padding (APP_ATTR (NORMAL), 0.25, 1)) | 		app_push (&l, g.ui->padding (attrs[0], 0.25, 1)); | ||||||
| 			->id = WIDGET_MESSAGE; | 		if (!g.message_detail) | ||||||
| 		app_push_fill (&l, g.ui->label (APP_ATTR (HIGHLIGHT), g.message)) | 			app_push_fill (&l, g.ui->label (attrs[1], g.message)); | ||||||
| 			->id = WIDGET_MESSAGE; | 		else | ||||||
| 		app_push (&l, g.ui->padding (APP_ATTR (NORMAL), 0.25, 1)) | 		{ | ||||||
| 			->id = WIDGET_MESSAGE; | 			app_push (&l, g.ui->label (attrs[1], g.message)); | ||||||
|  | 			app_push_fill (&l, g.ui->label (attrs[0], g.message_detail)); | ||||||
|  | 		} | ||||||
|  | 		app_push (&l, g.ui->padding (attrs[0], 0.25, 1)); | ||||||
|  | 
 | ||||||
| 		app_flush_layout (&l); | 		app_flush_layout (&l); | ||||||
|  | 		LIST_FOR_EACH (struct widget, w, l.head) | ||||||
|  | 			w->id = WIDGET_MESSAGE; | ||||||
| 	} | 	} | ||||||
| 	else if (g.editor.line) | 	else if (g.editor.line) | ||||||
| 	{ | 	{ | ||||||
| 		app_push (&l, g.ui->padding (APP_ATTR (NORMAL), 0.25, 1)); | 		app_push (&l, g.ui->padding (attrs[0], 0.25, 1)); | ||||||
| 		app_push (&l, g.ui->editor (APP_ATTR (HIGHLIGHT))); | 		app_push (&l, g.ui->editor (attrs[1])); | ||||||
| 		app_push (&l, g.ui->padding (APP_ATTR (NORMAL), 0.25, 1)); | 		app_push (&l, g.ui->padding (attrs[0], 0.25, 1)); | ||||||
| 		app_flush_layout (&l); | 		app_flush_layout (&l); | ||||||
| 	} | 	} | ||||||
| 	else if (g.client.state == MPD_CONNECTED) | 	else if (g.client.state == MPD_CONNECTED) | ||||||
| @ -2375,6 +2384,27 @@ app_move_selection (int diff) | |||||||
| 	return result; | 	return result; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void | ||||||
|  | app_show_message (char *message, char *detail) | ||||||
|  | { | ||||||
|  | 	cstr_set (&g.message, message); | ||||||
|  | 	cstr_set (&g.message_detail, detail); | ||||||
|  | 	poller_timer_set (&g.message_timer, 5000); | ||||||
|  | 	app_invalidate (); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | app_hide_message (void) | ||||||
|  | { | ||||||
|  | 	if (!g.message) | ||||||
|  | 		return; | ||||||
|  | 
 | ||||||
|  | 	cstr_set (&g.message, NULL); | ||||||
|  | 	cstr_set (&g.message_detail, NULL); | ||||||
|  | 	poller_timer_reset (&g.message_timer); | ||||||
|  | 	app_invalidate (); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| @ -2558,17 +2588,6 @@ app_mpd_toggle (const char *name) | |||||||
| 	return MPD_SIMPLE (name, value ? "0" : "1"); | 	return MPD_SIMPLE (name, value ? "0" : "1"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void |  | ||||||
| app_hide_message (void) |  | ||||||
| { |  | ||||||
| 	if (g.message) |  | ||||||
| 	{ |  | ||||||
| 		cstr_set (&g.message, NULL); |  | ||||||
| 		poller_timer_reset (&g.message_timer); |  | ||||||
| 		app_invalidate (); |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static bool | static bool | ||||||
| app_process_action (enum action action) | app_process_action (enum action action) | ||||||
| { | { | ||||||
| @ -2606,7 +2625,8 @@ app_process_action (enum action action) | |||||||
| 		app_hide_message (); | 		app_hide_message (); | ||||||
| 		return true; | 		return true; | ||||||
| 	default: | 	default: | ||||||
| 		print_error ("can't do that here: %s", g_action_descriptions[action]); | 		print_error ("\"%s\" is not allowed here", | ||||||
|  | 			g_action_descriptions[action]); | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	case ACTION_MULTISELECT: | 	case ACTION_MULTISELECT: | ||||||
| @ -2738,7 +2758,8 @@ app_editor_process_action (enum action action) | |||||||
| 		g.editor.on_end = NULL; | 		g.editor.on_end = NULL; | ||||||
| 		return true; | 		return true; | ||||||
| 	default: | 	default: | ||||||
| 		print_error ("can't do that here: %s", g_action_descriptions[action]); | 		print_error ("\"%s\" is not allowed here", | ||||||
|  | 			g_action_descriptions[action]); | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	case ACTION_EDITOR_B_CHAR: | 	case ACTION_EDITOR_B_CHAR: | ||||||
| @ -2962,6 +2983,7 @@ g_normal_defaults[] = | |||||||
| 	{ "Enter",      ACTION_CHOOSE             }, | 	{ "Enter",      ACTION_CHOOSE             }, | ||||||
| 	{ "Delete",     ACTION_DELETE             }, | 	{ "Delete",     ACTION_DELETE             }, | ||||||
| 	{ "d",          ACTION_DELETE             }, | 	{ "d",          ACTION_DELETE             }, | ||||||
|  | 	{ "?",          ACTION_DESCRIBE           }, | ||||||
| 	{ "M-Up",       ACTION_UP                 }, | 	{ "M-Up",       ACTION_UP                 }, | ||||||
| 	{ "Backspace",  ACTION_UP                 }, | 	{ "Backspace",  ACTION_UP                 }, | ||||||
| 	{ "v",          ACTION_MULTISELECT        }, | 	{ "v",          ACTION_MULTISELECT        }, | ||||||
| @ -3238,6 +3260,12 @@ current_tab_on_action (enum action action) | |||||||
| 		tab->item_mark = -1; | 		tab->item_mark = -1; | ||||||
| 		return map && (id = compact_map_find (map, "id")) | 		return map && (id = compact_map_find (map, "id")) | ||||||
| 			&& MPD_SIMPLE ("playid", id); | 			&& MPD_SIMPLE ("playid", id); | ||||||
|  | 	case ACTION_DESCRIBE: | ||||||
|  | 		if (!map || !(id = compact_map_find (map, "file"))) | ||||||
|  | 			return false; | ||||||
|  | 
 | ||||||
|  | 		app_show_message (xstrdup ("Path: "), xstrdup (id)); | ||||||
|  | 		return true; | ||||||
| 	case ACTION_DELETE: | 	case ACTION_DELETE: | ||||||
| 	{ | 	{ | ||||||
| 		struct mpd_client *c = &g.client; | 		struct mpd_client *c = &g.client; | ||||||
| @ -3652,6 +3680,12 @@ library_tab_on_action (enum action action) | |||||||
| 		} | 		} | ||||||
| 		tab->item_mark = -1; | 		tab->item_mark = -1; | ||||||
| 		return true; | 		return true; | ||||||
|  | 	case ACTION_DESCRIBE: | ||||||
|  | 		if (!*x->path) | ||||||
|  | 			break; | ||||||
|  | 
 | ||||||
|  | 		app_show_message (xstrdup ("Path: "), xstrdup (x->path)); | ||||||
|  | 		return true; | ||||||
| 	case ACTION_UP: | 	case ACTION_UP: | ||||||
| 	{ | 	{ | ||||||
| 		char *parent = library_tab_parent (); | 		char *parent = library_tab_parent (); | ||||||
| @ -3990,6 +4024,9 @@ streams_tab_on_action (enum action action) | |||||||
| 	case ACTION_MPD_ADD: | 	case ACTION_MPD_ADD: | ||||||
| 		streams_tab_process (uri, false, &e); | 		streams_tab_process (uri, false, &e); | ||||||
| 		break; | 		break; | ||||||
|  | 	case ACTION_DESCRIBE: | ||||||
|  | 		app_show_message (xstrdup (uri), NULL); | ||||||
|  | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		return false; | 		return false; | ||||||
| 	} | 	} | ||||||
| @ -4103,17 +4140,26 @@ help_tab_on_action (enum action action) | |||||||
| { | { | ||||||
| 	struct tab *tab = &g_help_tab.super; | 	struct tab *tab = &g_help_tab.super; | ||||||
| 	if (tab->item_selected < 0 | 	if (tab->item_selected < 0 | ||||||
| 	 || tab->item_selected >= (int) g_help_tab.actions_len | 	 || tab->item_selected >= (int) g_help_tab.actions_len) | ||||||
| 	 || action != ACTION_CHOOSE) |  | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	action = g_help_tab.actions[tab->item_selected]; | 	enum action a = g_help_tab.actions[tab->item_selected]; | ||||||
| 	if (action == ACTION_NONE || action == ACTION_CHOOSE /* avoid recursion */) | 	if (!a) | ||||||
|  | 		return false; | ||||||
|  | 
 | ||||||
|  | 	if (action == ACTION_DESCRIBE) | ||||||
|  | 	{ | ||||||
|  | 		char *name = xstrdup (g_action_names[a]); | ||||||
|  | 		cstr_transform (name, tolower_ascii); | ||||||
|  | 		app_show_message (xstrdup ("Configuration name: "), name); | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 	if (action != ACTION_CHOOSE || a == ACTION_CHOOSE /* avoid recursion */) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	// XXX: We can't propagate failure to ring the terminal/X11 bell, but we
 | 	// XXX: We can't propagate failure to ring the terminal/X11 bell, but we
 | ||||||
| 	//   don't want to let our caller show a bad "can't do that" message either.
 | 	//   don't want to let our caller show a bad "can't do that" message either.
 | ||||||
| 	return app_process_action (action), true; | 	return app_process_action (a), true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| @ -6078,11 +6124,8 @@ x11_process_press (int x, int y, int button, int modifiers) | |||||||
| 	cstr_set (&g.x11_selection, text); | 	cstr_set (&g.x11_selection, text); | ||||||
| 	XSetSelectionOwner (g.dpy, XInternAtom (g.dpy, "CLIPBOARD", False), | 	XSetSelectionOwner (g.dpy, XInternAtom (g.dpy, "CLIPBOARD", False), | ||||||
| 		g.x11_window, CurrentTime); | 		g.x11_window, CurrentTime); | ||||||
| 
 | 	app_show_message (xstrdup ("Text copied to clipboard: "), | ||||||
| 	cstr_set (&g.message, | 		xstrdup (g.x11_selection)); | ||||||
| 		xstrdup_printf ("Text copied to clipboard: %s", g.x11_selection)); |  | ||||||
| 	poller_timer_set (&g.message_timer, 5000); |  | ||||||
| 	app_invalidate (); |  | ||||||
| 	return true; | 	return true; | ||||||
| 
 | 
 | ||||||
| out: | out: | ||||||
| @ -6585,6 +6628,7 @@ app_on_message_timer (void *user_data) | |||||||
| 	(void) user_data; | 	(void) user_data; | ||||||
| 
 | 
 | ||||||
| 	cstr_set (&g.message, NULL); | 	cstr_set (&g.message, NULL); | ||||||
|  | 	cstr_set (&g.message_detail, NULL); | ||||||
| 	app_invalidate (); | 	app_invalidate (); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -6601,12 +6645,13 @@ app_log_handler (void *user_data, const char *quote, const char *fmt, | |||||||
| 
 | 
 | ||||||
| 	struct str message = str_make (); | 	struct str message = str_make (); | ||||||
| 	str_append (&message, quote); | 	str_append (&message, quote); | ||||||
|  | 	size_t quote_len = message.len; | ||||||
| 	str_append_vprintf (&message, fmt, ap); | 	str_append_vprintf (&message, fmt, ap); | ||||||
| 
 | 
 | ||||||
| 	// Show it to the user, then maybe log it elsewhere as well.
 | 	// Show it prettified to the user, then maybe log it elsewhere as well.
 | ||||||
| 	cstr_set (&g.message, xstrdup (message.str)); | 	message.str[0] = toupper_ascii (message.str[0]); | ||||||
| 	poller_timer_set (&g.message_timer, 5000); | 	app_show_message (xstrndup (message.str, quote_len), | ||||||
| 	app_invalidate (); | 		xstrdup (message.str + quote_len)); | ||||||
| 
 | 
 | ||||||
| 	if (g_verbose_mode && (g.ui != &tui_ui || !isatty (STDERR_FILENO))) | 	if (g_verbose_mode && (g.ui != &tui_ui || !isatty (STDERR_FILENO))) | ||||||
| 		fprintf (stderr, "%s\n", message.str); | 		fprintf (stderr, "%s\n", message.str); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user