Beispiel #1
0
void
cli_context_loop (cli_context_t *ctx, gint argc, gchar **argv)
{
	/* Execute command, if connection status is ok */
	if (argc == 0) {
		gchar *filename = configuration_get_string (ctx->config, "HISTORY_FILE");

		ctx->mode = CLI_EXECUTION_MODE_SHELL;

		/* print welcome message before initialising readline */
		if (configuration_get_boolean (ctx->config, "SHELL_START_MESSAGE")) {
			g_printf (_("Welcome to the XMMS2 CLI shell!\n"));
			g_printf (_("Type 'help' to list the available commands "
			            "and 'exit' (or CTRL-D) to leave the shell.\n"));
		}
		readline_resume (ctx);

		read_history (filename);
		using_history ();

		while (!cli_context_in_status (ctx, CLI_ACTION_STATUS_FINISH)) {
			cli_context_event_loop_select (ctx);
		}

		write_history (filename);
	} else {
		ctx->mode = CLI_EXECUTION_MODE_INLINE;
		cli_context_command_or_flag_dispatch (ctx, argc , argv);

		while (cli_context_in_status (ctx, CLI_ACTION_STATUS_BUSY) ||
		       cli_context_in_status (ctx, CLI_ACTION_STATUS_REFRESH)) {
			cli_context_event_loop_select (ctx);
		}
	}
}
Beispiel #2
0
static gboolean
cli_context_command_runnable (cli_context_t *ctx, command_action_t *action)
{
	xmmsc_connection_t *conn = cli_context_xmms_async (ctx);
	gint n = 0;

	/* Require connection, abort on failure */
	if (COMMAND_REQ_CHECK(action, COMMAND_REQ_CONNECTION) && !conn) {
		gboolean autostart;
		autostart = !COMMAND_REQ_CHECK(action, COMMAND_REQ_NO_AUTOSTART);
		if (!cli_context_connect (ctx, autostart) && autostart) {
			return FALSE;
		}
	}

	/* Get the cache ready if needed */
	if (COMMAND_REQ_CHECK(action, COMMAND_REQ_CACHE)) {
		/* If executing an alias have to refresh manually */
		if (cli_context_in_status (ctx, CLI_ACTION_STATUS_ALIAS)) {
			cli_context_cache_refresh (ctx);
		}
		while (cli_context_cache_refreshing (ctx)) {
			/* Obviously, there is a problem with updating the cache, abort */
			if (n == MAX_CACHE_REFRESH_LOOP) {
				g_printf (_("Failed to update the cache!"));
				return FALSE;
			}
			cli_context_event_loop_select (ctx);
			n++;
		}
	}

	return TRUE;
}
Beispiel #3
0
void
cli_context_execute_command (cli_context_t *ctx, gchar *input)
{
	while (input && *input == ' ') ++input;

	if (input == NULL) {
		if (!cli_context_in_status (ctx, CLI_ACTION_STATUS_ALIAS)) {
			/* End of stream, quit */
			cli_context_loop_stop (ctx);
			g_printf ("\n");
		}
	} else if (*input != 0) {
		gint argc;
		gchar **argv, *listop;
		GError *error = NULL;

		if ((listop = strchr (input, ';'))) {
			*listop++ = '\0';
		}

		if (g_shell_parse_argv (input, &argc, &argv, &error)) {
			if (!cli_context_in_status (ctx, CLI_ACTION_STATUS_ALIAS)) {
				add_history (input);
			}
			cli_context_command_dispatch (ctx, argc, argv);
			g_strfreev (argv);
			if (listop && *listop) {
				g_printf ("\n");
				cli_context_execute_command (ctx, listop);
			}
		} else {
			g_printf (_("Error: %s\n"), error->message);
			g_error_free (error);
		}
	}
}
Beispiel #4
0
void
readline_status_mode_exit (void)
{
	Keymap active;

	g_assert (cli_context_in_status (readline_cli_ctx, CLI_ACTION_STATUS_REFRESH));

	active = rl_get_keymap ();

	rl_set_keymap (rl_get_keymap_by_name (readline_keymap));
	rl_discard_keymap (active);

	rl_callback_handler_remove ();
	g_free (readline_keymap);
	status_free (cli_context_status_entry (readline_cli_ctx)); // TODO: handle via cli_context_free or somesuch?
	cli_context_status_mode_exit (readline_cli_ctx);
}
Beispiel #5
0
static void
cli_context_event_loop_select (cli_context_t *ctx)
{
	xmmsc_connection_t *conn = cli_context_xmms_async (ctx);
	fd_set rfds, wfds;
	gint modfds;
	gint xmms2fd;
	gint maxfds = 0;

	FD_ZERO(&rfds);
	FD_ZERO(&wfds);

	/* Listen to xmms2 if connected */
	if (conn) {
		xmms2fd = xmmsc_io_fd_get (conn);
		if (xmms2fd == -1) {
			g_printf (_("Error: failed to retrieve XMMS2 file descriptor!"));
			return;
		}

		FD_SET(xmms2fd, &rfds);
		if (xmmsc_io_want_out (conn)) {
			FD_SET(xmms2fd, &wfds);
		}

		if (maxfds < xmms2fd) {
			maxfds = xmms2fd;
		}
	}

	/* Listen to readline in shell mode or status mode */
	if ((cli_context_in_mode (ctx, CLI_EXECUTION_MODE_SHELL) &&
	     cli_context_in_status (ctx, CLI_ACTION_STATUS_READY)) ||
	    cli_context_in_status (ctx, CLI_ACTION_STATUS_REFRESH)) {
		FD_SET(STDIN_FILENO, &rfds);
		if (maxfds < STDIN_FILENO) {
			maxfds = STDIN_FILENO;
		}
	}

	if (cli_context_in_status (ctx, CLI_ACTION_STATUS_REFRESH)) {
		struct timeval refresh;
		refresh.tv_sec = cli_context_refresh_interval (ctx);
		refresh.tv_usec = 0;
		modfds = select (maxfds + 1, &rfds, &wfds, NULL, &refresh);
	} else {
		modfds = select (maxfds + 1, &rfds, &wfds, NULL, NULL);
	}

	if (modfds < 0 && errno != EINTR) {
		g_printf (_("Error: invalid I/O result!"));
		return;
	} else if (modfds != 0) {
		/* Get/send data to xmms2 */
		if (conn) {
			if (FD_ISSET(xmms2fd, &rfds) &&
			    !xmmsc_io_in_handle (conn)) {
				return;
			}

			if (FD_ISSET(xmms2fd, &wfds) &&
			    !xmmsc_io_out_handle (conn)) {
				return;
			}
		}

		/* User input found, read it */
		if ((cli_context_in_mode (ctx, CLI_EXECUTION_MODE_SHELL) ||
		     cli_context_in_status (ctx, CLI_ACTION_STATUS_REFRESH)) &&
		    FD_ISSET(STDIN_FILENO, &rfds)) {
			rl_callback_read_char ();
		}
	}

	/* Status -refresh
	   Ask theefer: use callbacks for update and -refresh only for print?
	   Nesciens: Yes, please!
	*/
	if (cli_context_in_status (ctx, CLI_ACTION_STATUS_REFRESH)) {
		cli_context_refresh_status (ctx);
	}
}