Exemple #1
0
bool
mpd_recv_queue_change_brief(struct mpd_connection *connection,
			    unsigned *position_r, unsigned *id_r)
{
	struct mpd_pair *pair;

	pair = mpd_recv_pair_named(connection, "cpos");
	if (pair == NULL)
		return false;

	*position_r = atoi(pair->value);
	mpd_return_pair(connection, pair);

	pair = mpd_recv_pair_named(connection, "Id");
	if (pair == NULL) {
		mpd_return_pair(connection, pair);

		if (!mpd_error_is_defined(&connection->error)) {
			mpd_error_code(&connection->error,
				       MPD_ERROR_MALFORMED);
			mpd_error_message(&connection->error,
					  "No id received");
		}

		return false;
	}

	*id_r = atoi(pair->value);
	mpd_return_pair(connection, pair);

	return !mpd_error_is_defined(&connection->error);
}
Exemple #2
0
struct mpd_stats *
mpd_recv_stats(struct mpd_connection *connection)
{
	struct mpd_stats * stats;
	struct mpd_pair *pair;

	assert(connection != NULL);

	if (mpd_error_is_defined(&connection->error))
		/* refuse to receive a response if the connection's
		   state is not clean */
		return NULL;

	stats = mpd_stats_begin();
	if (stats == NULL) {
		mpd_error_code(&connection->error, MPD_ERROR_OOM);
		return NULL;
	}

	/* read and parse all response lines */
	while ((pair = mpd_recv_pair(connection)) != NULL) {
		mpd_stats_feed(stats, pair);
		mpd_return_pair(connection, pair);
	}

	if (mpd_error_is_defined(&connection->error)) {
		/* an error has occurred; roll back */
		mpd_stats_free(stats);
		return NULL;
	}

	return stats;
}
Exemple #3
0
bool
mpd_search_commit(struct mpd_connection *connection)
{
	bool success;

	assert(connection != NULL);

	if (mpd_error_is_defined(&connection->error)) {
		mpd_search_cancel(connection);
		return false;
	}

	if (connection->request == NULL) {
		mpd_error_code(&connection->error, MPD_ERROR_STATE);
		mpd_error_message(&connection->error,
				  "no search in progress");
		return false;
	}

	success = mpd_send_command(connection, connection->request, NULL);
	free(connection->request);
	connection->request = NULL;

	return success;
}
Exemple #4
0
struct mpd_entity *
mpd_recv_entity(struct mpd_connection *connection)
{
	struct mpd_pair *pair;
	struct mpd_entity *entity;

	pair = mpd_recv_pair(connection);
	if (pair == NULL)
		return NULL;

	entity = mpd_entity_begin(pair);
	mpd_return_pair(connection, pair);
	if (entity == NULL) {
		mpd_error_entity(&connection->error);
		return NULL;
	}

	while ((pair = mpd_recv_pair(connection)) != NULL &&
	       mpd_entity_feed(entity, pair))
		mpd_return_pair(connection, pair);

	if (mpd_error_is_defined(&connection->error)) {
		mpd_entity_free(entity);
		return NULL;
	}

	/* unread this pair for the next mpd_recv_entity() call */
	mpd_enqueue_pair(connection, pair);

	return entity;
}
struct mpd_playlist *
mpd_recv_playlist(struct mpd_connection *connection)
{
	struct mpd_pair *pair;
	struct mpd_playlist *playlist;

	pair = mpd_recv_pair_named(connection, "playlist");
	if (pair == NULL)
		return NULL;

	playlist = mpd_playlist_begin(pair);
	mpd_return_pair(connection, pair);
	if (playlist == NULL) {
		mpd_error_code(&connection->error, MPD_ERROR_OOM);
		return NULL;
	}

	while ((pair = mpd_recv_pair(connection)) != NULL &&
	       mpd_playlist_feed(playlist, pair))
		mpd_return_pair(connection, pair);

	if (mpd_error_is_defined(&connection->error)) {
		assert(pair == NULL);

		mpd_playlist_free(playlist);
		return NULL;
	}

	/* unread this pair for the next mpd_recv_playlist() call */
	mpd_enqueue_pair(connection, pair);

	return playlist;
}
Exemple #6
0
struct mpd_song *
mpd_recv_song(struct mpd_connection *connection)
{
	struct mpd_pair *pair;
	struct mpd_song *song;

	pair = mpd_recv_pair_named(connection, "file");
	if (pair == NULL)
		return NULL;

	song = mpd_song_begin(pair);
	mpd_return_pair(connection, pair);
	if (song == NULL) {
		mpd_error_entity(&connection->error);
		return NULL;
	}

	while ((pair = mpd_recv_pair(connection)) != NULL &&
	       mpd_song_feed(song, pair))
		mpd_return_pair(connection, pair);

	if (mpd_error_is_defined(&connection->error)) {
		mpd_song_free(song);
		return NULL;
	}

	/* unread this pair for the next mpd_recv_song() call */
	mpd_enqueue_pair(connection, pair);

	return song;
}
Exemple #7
0
struct mpd_directory *
mpd_recv_directory(struct mpd_connection *connection)
{
	struct mpd_pair *pair;
	struct mpd_directory *directory;

	pair = mpd_recv_pair_named(connection, "directory");
	if (pair == NULL)
		return NULL;

	directory = mpd_directory_begin(pair);
	mpd_return_pair(connection, pair);
	if (directory == NULL) {
		mpd_error_entity(&connection->error);
		return NULL;
	}

	while ((pair = mpd_recv_pair(connection)) != NULL &&
	       mpd_directory_feed(directory, pair))
		mpd_return_pair(connection, pair);

	if (mpd_error_is_defined(&connection->error)) {
		assert(pair == NULL);

		mpd_directory_free(directory);
		return NULL;
	}

	/* unread this pair for the next mpd_recv_directory() call */
	mpd_enqueue_pair(connection, pair);

	return directory;
}
Exemple #8
0
void
mpd_error_message(struct mpd_error_info *error, const char *message)
{
	assert(error != NULL);
	assert(message != NULL);
	assert(mpd_error_is_defined(error));
	assert(error->message == NULL);

	error->message = strdup(message);
	if (error->message == NULL)
		error->code = MPD_ERROR_OOM;
}
Exemple #9
0
void
mpd_error_message_n(struct mpd_error_info *error,
		    const char *message, size_t length)
{
	assert(error != NULL);
	assert(message != NULL);
	assert(mpd_error_is_defined(error));
	assert(error->message == NULL);

	error->message = malloc(length + 1);
	if (error->message != NULL) {
		memcpy(error->message, message, length);
		error->message[length] = 0;
	} else
		error->code = MPD_ERROR_OOM;
}
Exemple #10
0
static bool
mpd_search_add_constraint(struct mpd_connection *connection,
			  mpd_unused enum mpd_operator oper,
			  const char *name,
			  const char *value)
{
	size_t old_length, add_length;
	char *arg, *request;

	assert(connection != NULL);
	assert(name != NULL);
	assert(value != NULL);

	if (mpd_error_is_defined(&connection->error))
		return false;

	if (!connection->request) {
		mpd_error_code(&connection->error, MPD_ERROR_STATE);
		mpd_error_message(&connection->error,
				  "no search in progress");
		return false;
	}

	old_length = strlen(connection->request);

	arg = mpd_sanitize_arg(value);
	if (arg == NULL) {
		mpd_error_code(&connection->error, MPD_ERROR_OOM);
		return false;
	}

	add_length = 1 + strlen(name) + 2 + strlen(arg) + 2;
	request = realloc(connection->request, old_length + add_length);
	if (request == NULL) {
		free(arg);
		mpd_error_code(&connection->error, MPD_ERROR_OOM);
		return false;
	}

	connection->request = request;
	snprintf(connection->request + old_length, add_length,
		 " %s \"%s\"", name, arg);

	free(arg);
	return true;
}
Exemple #11
0
/**
 * Checks whether it is possible to run a command now.
 */
bool
mpd_run_check(struct mpd_connection *connection)
{
	assert(connection != NULL);

	if (mpd_error_is_defined(&connection->error))
		return false;

	if (connection->sending_command_list) {
		mpd_error_code(&connection->error, MPD_ERROR_STATE);
		mpd_error_message(&connection->error,
				  "Not possible in command list mode");
		return false;
	}

	return true;
}
Exemple #12
0
struct mpd_message *
mpd_recv_message(struct mpd_connection *connection)
{
	struct mpd_message *message;
	struct mpd_pair *pair;

	pair = mpd_recv_pair_named(connection, "channel");
	if (pair == NULL)
		return NULL;

	message = mpd_message_begin(pair);
	mpd_return_pair(connection, pair);
	if (message == NULL) {
		mpd_error_code(&connection->error, MPD_ERROR_OOM);
		return NULL;
	}

	while ((pair = mpd_recv_pair(connection)) != NULL &&
	       mpd_message_feed(message, pair))
		mpd_return_pair(connection, pair);

	if (mpd_error_is_defined(&connection->error)) {
		assert(pair == NULL);

		mpd_message_free(message);
		return NULL;
	}

	mpd_enqueue_pair(connection, pair);

	if (mpd_message_get_text(message) == NULL) {
		mpd_error_code(&connection->error, MPD_ERROR_MALFORMED);
		mpd_error_message(&connection->error,
				  "No 'message' line received");
		mpd_message_free(message);
		return NULL;
	}

	return message;
}
Exemple #13
0
bool
mpd_count_db_songs(struct mpd_connection *connection)
{
	assert(connection != NULL);

	if (mpd_error_is_defined(&connection->error))
		return false;

	if (connection->request) {
		mpd_error_code(&connection->error, MPD_ERROR_STATE);
		mpd_error_message(&connection->error,
				  "search already in progress");
		return false;
	}

	connection->request = strdup("count");
	if (connection->request == NULL) {
		mpd_error_code(&connection->error, MPD_ERROR_OOM);
		return false;
	}

	return true;
}
Exemple #14
0
bool
mpd_search_db_tags(struct mpd_connection *connection, enum mpd_tag_type type)
{
	const char *strtype;
	int len;

	assert(connection != NULL);

	if (mpd_error_is_defined(&connection->error))
		return false;

	if (connection->request) {
		mpd_error_code(&connection->error, MPD_ERROR_STATE);
		mpd_error_message(&connection->error,
				  "search already in progress");
		return false;
	}

	strtype = mpd_tag_name(type);
	if (strtype == NULL) {
		mpd_error_code(&connection->error, MPD_ERROR_ARGUMENT);
		mpd_error_message(&connection->error,
				  "invalid type specified");
		return false;
	}

	len = 5+strlen(strtype)+1;
	connection->request = malloc(len);
	if (connection->request == NULL) {
		mpd_error_code(&connection->error, MPD_ERROR_OOM);
		return false;
	}

	snprintf(connection->request, len, "list %s", strtype);

	return true;
}
Exemple #15
0
static bool
mpd_search_init(struct mpd_connection *connection, const char *cmd)
{
	assert(connection != NULL);
	assert(cmd != NULL);

	if (mpd_error_is_defined(&connection->error))
		return false;

	if (connection->request) {
		mpd_error_code(&connection->error, MPD_ERROR_STATE);
		mpd_error_message(&connection->error,
				  "search already in progress");
		return false;
	}

	connection->request = strdup(cmd);
	if (connection->request == NULL) {
		mpd_error_code(&connection->error, MPD_ERROR_OOM);
		return false;
	}

	return true;
}
Exemple #16
0
struct mpd_pair *
mpd_recv_pair(struct mpd_connection *connection)
{
	struct mpd_pair *pair;
	char *line;
	enum mpd_parser_result result;
	const char *msg;

	assert(connection != NULL);

	if (mpd_error_is_defined(&connection->error))
		return NULL;

	/* check if the caller has returned the previous pair */
	assert(connection->pair_state != PAIR_STATE_FLOATING);

	if (connection->pair_state == PAIR_STATE_NULL) {
		/* return the enqueued NULL pair */
		connection->pair_state = PAIR_STATE_NONE;
		return NULL;
	}

	if (connection->pair_state == PAIR_STATE_QUEUED) {
		/* dequeue the pair from mpd_enqueue_pair() */
		pair = &connection->pair;
		connection->pair_state = PAIR_STATE_FLOATING;
		return pair;
	}

	assert(connection->pair_state == PAIR_STATE_NONE);

	if (!connection->receiving ||
	    (connection->sending_command_list &&
	     connection->command_list_remaining > 0 &&
	     connection->discrete_finished)) {
		mpd_error_code(&connection->error, MPD_ERROR_STATE);
		mpd_error_message(&connection->error,
				  "already done processing current command");
		return NULL;
	}

	line = mpd_sync_recv_line(connection->async,
				  mpd_connection_timeout(connection));
	if (line == NULL) {
		connection->receiving = false;
		connection->sending_command_list = false;

		mpd_connection_sync_error(connection);
		return NULL;
	}

	result = mpd_parser_feed(connection->parser, line);
	switch (result) {
	case MPD_PARSER_MALFORMED:
		mpd_error_code(&connection->error, MPD_ERROR_MALFORMED);
		mpd_error_message(&connection->error,
				  "Failed to parse MPD response");
		connection->receiving = false;
		return NULL;

	case MPD_PARSER_SUCCESS:
		if (!mpd_parser_is_discrete(connection->parser)) {
			if (connection->sending_command_list &&
			    connection->command_list_remaining > 0) {
				mpd_error_code(&connection->error,
					       MPD_ERROR_MALFORMED);
				mpd_error_message(&connection->error,
						  "expected more list_OK's");
				connection->command_list_remaining = 0;
			}

			connection->receiving = false;
			connection->sending_command_list = false;
			connection->discrete_finished = false;
		} else {
			if (!connection->sending_command_list ||
			    connection->command_list_remaining == 0) {
				mpd_error_code(&connection->error,
					       MPD_ERROR_MALFORMED);
				mpd_error_message(&connection->error,
						  "got an unexpected list_OK");
			} else {
				connection->discrete_finished = true;
				--connection->command_list_remaining;
			}
		}

		return NULL;

	case MPD_PARSER_ERROR:
		connection->receiving = false;
		connection->sending_command_list = false;
		mpd_error_server(&connection->error,
				 mpd_parser_get_server_error(connection->parser),
				 mpd_parser_get_at(connection->parser));
		msg = mpd_parser_get_message(connection->parser);
		if (msg == NULL)
			msg = "Unspecified MPD error";
		mpd_error_message(&connection->error, msg);
		return NULL;

	case MPD_PARSER_PAIR:
		pair = &connection->pair;
		pair->name = mpd_parser_get_name(connection->parser);
		pair->value = mpd_parser_get_value(connection->parser);

		connection->pair_state = PAIR_STATE_FLOATING;
		return pair;
	}

	/* unreachable */
	assert(false);
	return NULL;
}