Beispiel #1
0
void
filelist_recv(struct filelist *filelist, struct mpd_connection *connection)
{
	struct mpd_entity *entity;

	while ((entity = mpd_recv_entity(connection)) != NULL)
		filelist_append(filelist, entity);
}
Beispiel #2
0
void get_random_song(struct mpd_connection *conn, char *str, char *path)
{
    struct mpd_entity *entity;
    int listened0 = 65000,
        skipnum, numberofsongs = 0;

    struct mpd_stats *stats = mpd_run_stats(conn);
    if (stats == NULL)
        return;
    numberofsongs = mpd_stats_get_number_of_songs(stats);
    mpd_stats_free(stats);
    skipnum = rand() % numberofsongs;

    syslog(LOG_DEBUG, "%s: path %s; number of songs: %i skip: %i\n",
            __func__, path, numberofsongs, skipnum);
    if (!mpd_send_list_all_meta(conn, ""))//path))
    {
        syslog(LOG_ERR, "%s: error: mpd_send_list_meta %s\n", __func__, path);
        return;
    }

    while((entity = mpd_recv_entity(conn)) != NULL)
    {
        const struct mpd_song *song;
        if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG)
        {
            if (skipnum-- > 0)
                continue;

            int listened;
            song = mpd_entity_get_song(entity);
            listened = db_get_song_numplayed(mpd_get_title(song),
                    mpd_get_artist(song));
            if (listened < listened0) {
                listened0 = listened;
                syslog(LOG_DEBUG, "listened: %i ", listened);
                int probability = 50 +
                    db_get_song_rating(mpd_get_title(song),
                            mpd_get_artist(song));
                syslog(LOG_DEBUG, "probability: %i ", probability);
                bool Yes = (rand() % 100) < probability;
                if (Yes) {
                    sprintf(str, "%s", mpd_song_get_uri(song));
                    syslog(LOG_DEBUG, "uri: %s ", str);
                    syslog(LOG_DEBUG, "title: %s ", mpd_get_title(song));
                    syslog(LOG_DEBUG, "artist: %s", mpd_get_artist(song));
                }
            }
        }
        mpd_entity_free(entity);
    }
}
Beispiel #3
0
/* create a list suitable for GCompletion from path */
GList *
gcmp_list_from_path(struct mpdclient *c, const gchar *path,
		    GList *list, gint types)
{
	struct mpd_connection *connection;
	struct mpd_entity *entity;

	connection = mpdclient_get_connection(c);
	if (connection == NULL)
		return list;

	mpd_send_list_meta(connection, path);

	while ((entity = mpd_recv_entity(connection)) != NULL) {
		char *name;

		if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_DIRECTORY &&
		    types & GCMP_TYPE_DIR) {
			const struct mpd_directory *dir =
				mpd_entity_get_directory(entity);
			gchar *tmp = utf8_to_locale(mpd_directory_get_path(dir));
			gsize size = strlen(tmp)+2;

			name = g_malloc(size);
			g_strlcpy(name, tmp, size);
			g_strlcat(name, "/", size);
			g_free(tmp);
		} else if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG &&
			   types & GCMP_TYPE_FILE) {
			const struct mpd_song *song =
				mpd_entity_get_song(entity);
			name = utf8_to_locale(mpd_song_get_uri(song));
		} else if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_PLAYLIST &&
			   types & GCMP_TYPE_PLAYLIST) {
			const struct mpd_playlist *playlist =
				mpd_entity_get_playlist(entity);
			name = utf8_to_locale(mpd_playlist_get_path(playlist));
		} else {
			mpd_entity_free(entity);
			continue;
		}

		list = g_list_append(list, name);
		mpd_entity_free(entity);
	}

	return list;
}
Beispiel #4
0
/*
 * Retrieves current playlist from MPD
 * TODO: implement missing entity types
 */
bool
Control::update_queue()
{
	bool			rc;
	Song *			song;
	struct mpd_entity *	ent;
	const struct mpd_song *	ent_song;

	EXIT_IDLE;

	pms->log(MSG_DEBUG, 0, "Updating playlist from version %d to %d\n", st->last_playlist, st->playlist);

	if (st->last_playlist == -1) {
		_queue->clear();
	}

	if (!mpd_send_queue_changes_meta(conn->h(), st->last_playlist)) {
		return false;
	}

	while ((ent = mpd_recv_entity(conn->h())) != NULL)
	{
		switch(mpd_entity_get_type(ent))
		{
			case MPD_ENTITY_TYPE_SONG:
				ent_song = mpd_entity_get_song(ent);
				song = new Song(ent_song);
				_queue->add_local(song);
				break;
			case MPD_ENTITY_TYPE_UNKNOWN:
				pms->log(MSG_DEBUG, 0, "BUG in update_queue(): entity type not implemented by libmpdclient\n");
				break;
			default:
				pms->log(MSG_DEBUG, 0, "BUG in update_queue(): entity type not implemented by PMS\n");
				break;
		}
		mpd_entity_free(ent);
	}

	if ((rc = get_error_bool()) == true) {
		_queue->truncate_local(st->playlist_length);
		st->last_playlist = st->playlist;
	}

	return rc;
}
Beispiel #5
0
/*
 * Retrieve the contents of a stored playlist. Will synchronize local playlists
 * with the MPD server, overwriting the local versions.
 *
 * Returns true on success, false on failure.
 */
bool
Control::update_playlist(Playlist * playlist)
{
	Song *			song;
	mpd_entity *		ent;
	const mpd_song *	ent_song;

	EXIT_IDLE;

	pms->log(MSG_DEBUG, 0, "Retrieving playlist %s from MPD server.\n", playlist->filename.c_str());

	if (!mpd_send_list_playlist_meta(conn->h(), playlist->filename.c_str())) {
		return false;
	}

	playlist->clear();

	while ((ent = mpd_recv_entity(conn->h())) != NULL)
	{
		switch(mpd_entity_get_type(ent))
		{
			case MPD_ENTITY_TYPE_SONG:
				ent_song = mpd_entity_get_song(ent);
				song = new Song(ent_song);
				song->id = MPD_SONG_NO_ID;
				song->pos = MPD_SONG_NO_NUM;
				playlist->add_local(song);
				break;
			case MPD_ENTITY_TYPE_UNKNOWN:
				pms->log(MSG_DEBUG, 0, "BUG in retrieve_lists(): entity type not implemented by libmpdclient\n");
				break;
			default:
				pms->log(MSG_DEBUG, 0, "BUG in retrieve_lists(): entity type not implemented by PMS\n");
				break;
		}
		mpd_entity_free(ent);
	}

	playlist->set_column_size();

	return get_error_bool();
}
Beispiel #6
0
void get_song_to_delete(char *str)
{
    struct mpd_entity *entity;
    int rating0 = 65000;
    if (!mpd_send_list_meta(mpd.conn, "/")) {
        syslog(LOG_DEBUG, "error: mpd_send_list_meta\n");
        return;
    }
    while((entity = mpd_recv_entity(mpd.conn)) != NULL) {
        if (mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) {
            const struct mpd_song *song = mpd_entity_get_song(entity);
            int rating = db_get_song_rating(mpd_get_title(song),
                    mpd_get_artist(song));
            if (rating < rating0) {
                rating0 = rating;
                sprintf(str, "%s", mpd_song_get_uri(song));
            }
        }
        mpd_entity_free(entity);
    }
}
Beispiel #7
0
int mpd_put_queue(char *buffer, unsigned int offset)
{
    char *cur = buffer;
    const char *end = buffer + MAX_SIZE;
    struct mpd_entity *entity;

    if (!mpd_send_list_queue_range_meta(mpd.conn, offset, offset+MAX_ELEMENTS_PER_PAGE))
        RETURN_ERROR_AND_RECOVER("mpd_send_list_queue_meta");

    cur += json_emit_raw_str(cur, end  - cur, "{\"type\":\"queue\",\"data\":[ ");

    while((entity = mpd_recv_entity(mpd.conn)) != NULL) {
        const struct mpd_song *song;

        if(mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG) {
            song = mpd_entity_get_song(entity);

            cur += json_emit_raw_str(cur, end - cur, "{\"id\":");
            cur += json_emit_int(cur, end - cur, mpd_song_get_id(song));
            cur += json_emit_raw_str(cur, end - cur, ",\"pos\":");
            cur += json_emit_int(cur, end - cur, mpd_song_get_pos(song));
            cur += json_emit_raw_str(cur, end - cur, ",\"duration\":");
            cur += json_emit_int(cur, end - cur, mpd_song_get_duration(song));
            cur += json_emit_raw_str(cur, end - cur, ",\"artist\":");
            cur += json_emit_quoted_str(cur, end - cur, mpd_get_artist(song));
            cur += json_emit_raw_str(cur, end - cur, ",\"album\":");
            cur += json_emit_quoted_str(cur, end - cur, mpd_get_album(song));
            cur += json_emit_raw_str(cur, end - cur, ",\"title\":");
            cur += json_emit_quoted_str(cur, end - cur, mpd_get_title(song));
            cur += json_emit_raw_str(cur, end - cur, "},");
        }
        mpd_entity_free(entity);
    }

    /* remove last ',' */
    cur--;

    cur += json_emit_raw_str(cur, end - cur, "]}");
    return cur - buffer;
}
Beispiel #8
0
void print_entity_list(struct mpd_connection *c, enum mpd_entity_type filter_type)
{
    struct mpd_entity *entity;
    while ((entity = mpd_recv_entity(c)) != NULL) {
        const struct mpd_directory *dir;
        const struct mpd_song *song;
        const struct mpd_playlist *playlist;

        enum mpd_entity_type type = mpd_entity_get_type(entity);
        if (filter_type != MPD_ENTITY_TYPE_UNKNOWN &&
            type != filter_type)
            type = MPD_ENTITY_TYPE_UNKNOWN;

        switch (type) {
        case MPD_ENTITY_TYPE_UNKNOWN:
            break;

        case MPD_ENTITY_TYPE_DIRECTORY:
            dir = mpd_entity_get_directory(entity);
            printf("%s\n", mpd_directory_get_path(dir)); //charset_from_utf8(mpd_directory_get_path(dir)));
            break;

        case MPD_ENTITY_TYPE_SONG:
            song = mpd_entity_get_song(entity);
            /*if (options.custom_format) {
                pretty_print_song(song);
                puts("");
            } else*/
                printf("%s\n", mpd_song_get_uri(song)); //charset_from_utf8(mpd_song_get_uri(song)));
            break;

        case MPD_ENTITY_TYPE_PLAYLIST:
            playlist = mpd_entity_get_playlist(entity);
            printf("%s\n", mpd_playlist_get_path(playlist)); //charset_from_utf8(mpd_playlist_get_path(playlist)));
            break;
        }

        mpd_entity_free(entity);
    }
}
Beispiel #9
0
bool mpd_is_in_queue(const char *uri)
{
    bool res = false;
    struct mpd_entity *entity;
    struct mpd_connection *conn = mpd_connection_new(NULL, NULL, 3000);

    if (conn == NULL) {
        syslog(LOG_ERR, "%s - Out of memory.", __func__);
        goto DONE;
    }
    if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS) {
        syslog(LOG_ERR, "%s - MPD connection: %s\n", __func__,
                mpd_connection_get_error_message(conn));
        goto DONE;
    }
    if (!mpd_send_list_queue_meta(conn)) {
        syslog(LOG_ERR, "%s: %s", __func__, mpd_connection_get_error_message(conn));
        mpd_connection_clear_error(conn);
        goto DONE;
    }
    while((entity = mpd_recv_entity(conn)) != NULL) {
        const struct mpd_song *song;
        if(mpd_entity_get_type(entity) == MPD_ENTITY_TYPE_SONG && !res) {
            song = mpd_entity_get_song(entity);
            if (strcmp(mpd_song_get_uri(song), uri) == 0) {
                syslog(LOG_INFO, "%s: %s is already in the queue", __func__, uri);
                res = true;
            }
        }
        mpd_entity_free(entity);
    }

DONE:
    if(conn != NULL)
        mpd_connection_free(conn);
    return res;
}
Beispiel #10
0
int mpd_put_browse(char *buffer, char *path, unsigned int offset)
{
    char *cur = buffer;
    const char *end = buffer + MAX_SIZE;
    struct mpd_entity *entity;
    unsigned int entity_count = 0;

    if (!mpd_send_list_meta(mpd.conn, path))
        RETURN_ERROR_AND_RECOVER("mpd_send_list_meta");

    cur += json_emit_raw_str(cur, end  - cur, "{\"type\":\"browse\",\"data\":[ ");

    while((entity = mpd_recv_entity(mpd.conn)) != NULL) {
        const struct mpd_song *song;
        const struct mpd_directory *dir;
        const struct mpd_playlist *pl;

        if(offset > entity_count)
        {
            mpd_entity_free(entity);
            entity_count++;
            continue;
        }
        else if(offset + MAX_ELEMENTS_PER_PAGE - 1 < entity_count)
        {
            mpd_entity_free(entity);
            cur += json_emit_raw_str(cur, end  - cur, "{\"type\":\"wrap\",\"count\":");
            cur += json_emit_int(cur, end - cur, entity_count);
            cur += json_emit_raw_str(cur, end  - cur, "} ");
            break;
        }

        switch (mpd_entity_get_type(entity)) {
            case MPD_ENTITY_TYPE_UNKNOWN:
                break;

            case MPD_ENTITY_TYPE_SONG:
                song = mpd_entity_get_song(entity);
                cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"song\",\"uri\":");
                cur += json_emit_quoted_str(cur, end - cur, mpd_song_get_uri(song));
                cur += json_emit_raw_str(cur, end - cur, ",\"duration\":");
                cur += json_emit_int(cur, end - cur, mpd_song_get_duration(song));
                cur += json_emit_raw_str(cur, end - cur, ",\"title\":");
                cur += json_emit_quoted_str(cur, end - cur, mpd_get_title(song));
                cur += json_emit_raw_str(cur, end - cur, "},");
                break;

            case MPD_ENTITY_TYPE_DIRECTORY:
                dir = mpd_entity_get_directory(entity);

                cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"directory\",\"dir\":");
                cur += json_emit_quoted_str(cur, end - cur, mpd_directory_get_path(dir));
                cur += json_emit_raw_str(cur, end - cur, "},");
                break;

            case MPD_ENTITY_TYPE_PLAYLIST:
                pl = mpd_entity_get_playlist(entity);
                cur += json_emit_raw_str(cur, end - cur, "{\"type\":\"playlist\",\"plist\":");
                cur += json_emit_quoted_str(cur, end - cur, mpd_playlist_get_path(pl));
                cur += json_emit_raw_str(cur, end - cur, "},");
                break;
        }
        mpd_entity_free(entity);
        entity_count++;
    }

    if (mpd_connection_get_error(mpd.conn) != MPD_ERROR_SUCCESS || !mpd_response_finish(mpd.conn)) {
        fprintf(stderr, "MPD mpd_send_list_meta: %s\n", mpd_connection_get_error_message(mpd.conn));
        mpd.conn_state = MPD_FAILURE;
        return 0;
    }

    /* remove last ',' */
    cur--;

    cur += json_emit_raw_str(cur, end - cur, "]}");
    return cur - buffer;
}
Beispiel #11
0
/*
 * returns: 0 - error; 1 - ok 
 */
int mqr_update_playlist() {
	struct mpd_entity *entity;
	const struct mpd_directory *dir;
	// const struct mpd_song *song;
	const char *path;

	char *toplevel_dirs[256];
	int array_sz = 0;
	int i;

	// Clear current playlist (QUEUE)
	if (!mpd_run_clear(conn)) {
		fprintf(stderr, "ERROR: MPD: Unable to clear the current playlist\n");
	} else
		if (DEBUG)
			fprintf(stderr, "DEBUG: [mgr-thread] mpd: playlist cleared\n");

	// list items & add to the playlist
	mpd_send_list_all(conn, NULL);
	while ((entity = mpd_recv_entity(conn)) != NULL) {
		path = NULL;

		switch (mpd_entity_get_type(entity)) {
			case MPD_ENTITY_TYPE_UNKNOWN:
				break;
			case MPD_ENTITY_TYPE_SONG:
				// ignore top level items
				// song = mpd_entity_get_song(entity);
				// path = mpd_song_get_uri(song);
				// if (strchr(path, '/') == NULL) {
				//	printf("FOUND SON %s\n", path);
				// }
				break;
			case MPD_ENTITY_TYPE_DIRECTORY:
				// check if has subfolders
				dir = mpd_entity_get_directory(entity);
				path = mpd_directory_get_path(dir);
				if (strchr(path, '/') != NULL)
					path = NULL;
				break;
			case MPD_ENTITY_TYPE_PLAYLIST:
				break;
				
		}

		if (path != NULL && array_sz < 255) {
			toplevel_dirs[ array_sz++ ] = strdup( path );
		}

		mpd_entity_free(entity);
	}
	mpd_response_finish(conn);

	for (i = 0; i < array_sz; i++) {
		if (!mpd_run_add(conn, toplevel_dirs[i])) {
			fprintf(stderr, "ERROR: MPD: Unable to add item to the file playlist: %s\n", toplevel_dirs[i]);
			continue;
		}

		if (DEBUG)
			fprintf(stderr, "DEBUG: [mgr-thread]: mpd: entry added to the playlist: %s\n", toplevel_dirs[i]);

		free( toplevel_dirs[i] );
	}

	return 1;
}
Beispiel #12
0
/* fetch a new db tree on root */
static int fetch_db_tree(DB_NODE **p_root,struct mpd_connection *conn)
{
    if (*p_root)
        return 1;

    /* create root */
    DB_NODE *root = (DB_NODE*)malloc(sizeof(DB_NODE));
    root->type = DB_DIRECTORY;
    /* use calloc for root->uri to ease free_db_tree() */
    root->uri = (char *)calloc(2,sizeof(char));
    strncpy(root->uri,"/",1);
    root->rating = 0;
    root->duration = 0;
    root->p = NULL;
    root->s = NULL;
    root->c = NULL;
    root->num_c = 0;

    /* set top node */
    DB_NODE *top = root;

	if (!mpd_send_list_all_meta(conn,"/")) {
        clear_or_exit_on_error(conn);
        return 1;
    }

    /* add nodes recursively */
    struct mpd_entity *entity;
	while ((entity = mpd_recv_entity(conn))) {

        DB_NODE *node = (DB_NODE*)malloc(sizeof(DB_NODE));

        const char *name = NULL;
        switch (mpd_entity_get_type(entity)) {
            case MPD_ENTITY_TYPE_DIRECTORY:
                node->type = DB_DIRECTORY;

                name = mpd_directory_get_path(mpd_entity_get_directory(entity));
                assert (name && strlen(name));
                node->uri = (char *)calloc(strlen(name)+1,sizeof(char));
                strncpy(node->uri,name,strlen(name));

                node->rating = 0;
                node->duration = 0;
                break;
            case MPD_ENTITY_TYPE_SONG:
                node->type = DB_SONG;

                name = mpd_song_get_uri(mpd_entity_get_song(entity));
                assert (name && strlen(name));
                node->uri = (char *)calloc(strlen(name)+1,sizeof(char));
                strncpy(node->uri,name,strlen(name));

                node->rating = 0;
                node->duration = mpd_song_get_duration(mpd_entity_get_song(entity));
                break;
            case MPD_ENTITY_TYPE_PLAYLIST:
                node->type = DB_PLAYLIST;

                name = mpd_playlist_get_path(mpd_entity_get_playlist(entity));
                assert (name && strlen(name));
                node->uri = (char *)calloc(strlen(name)+1,sizeof(char));
                strncpy(node->uri,name,strlen(name));

                node->rating = 0;
                node->duration = 0;
                break;
            case MPD_ENTITY_TYPE_UNKNOWN:
                break;
        }

        /* backtrace top until it's parent of node */
        while (top != root && !(strstr(node->uri,top->uri) && node->uri[strlen(top->uri)] == '/'))
            top = top->p;

        /* if current top already has chlidren */
        if (top->c) {
            DB_NODE *node2 = top->c;
            /* find the last child */
            while (node2->s)
                node2 = node2->s;
            node2->s = node;
            node->p = node2->p;
            node->p->num_c++;
        } else {
            top->c = node;
            node->p = top;
            node->p->num_c++;
        }
        /* no child, no next sibling */
        node->c = NULL;
        node->s = NULL;
        node->num_c = 0;

        /* update top node */
        if (node->type == DB_DIRECTORY)
            top = node;

		mpd_entity_free(entity);
	}
    if (mpd_connection_get_error(conn) == MPD_ERROR_SUCCESS)
        mpd_response_finish(conn);
    else if (!mpd_connection_clear_error(conn))
        exit_on_error(conn);

    *p_root = root;
    return 0;
}
Beispiel #13
0
/*
 * Retrieves the entire song library from MPD
 */
bool
Control::update_library()
{
	uint32_t			total = 0;
	Song *				song;
	struct mpd_entity *		ent;
	const struct mpd_directory *	ent_directory;
	const struct mpd_song *		ent_song;
	const struct mpd_playlist *	ent_playlist;
	Directory *			dir = rootdir;

	EXIT_IDLE;

	pms->log(MSG_DEBUG, 0, "Updating library from DB time %d to %d\n", st->last_db_update_time, st->db_update_time);
	st->last_db_update_time = st->db_update_time;

	if (!mpd_send_list_all_meta(conn->h(), "")) {
		return false;
	}

	_library->clear();

	while ((ent = mpd_recv_entity(conn->h())) != NULL)
	{
		switch(mpd_entity_get_type(ent))
		{
			case MPD_ENTITY_TYPE_SONG:
				ent_song = mpd_entity_get_song(ent);
				song = new Song(ent_song);
				song->id = MPD_SONG_NO_ID;
				song->pos = MPD_SONG_NO_NUM;
				_library->add_local(song);
				dir->songs.push_back(song);
				break;
			case MPD_ENTITY_TYPE_PLAYLIST:
				/* Issue #8: https://github.com/ambientsound/pms/issues/8 */
				ent_playlist = mpd_entity_get_playlist(ent);
				//pms->log(MSG_DEBUG, 0, "NOT IMPLEMENTED in update_library(): got playlist entity in update_library(): %s\n", mpd_playlist_get_path(ent_playlist));
				break;
			case MPD_ENTITY_TYPE_DIRECTORY:
				ent_directory = mpd_entity_get_directory(ent);
				dir = rootdir->add(mpd_directory_get_path(ent_directory));
				assert(dir != NULL);
				/*
				if (dir == NULL)
				{
					dir = rootdir;
				}
				*/
				break;
			case MPD_ENTITY_TYPE_UNKNOWN:
				pms->log(MSG_DEBUG, 0, "BUG in update_library(): entity type not implemented by libmpdclient\n");
				break;
			default:
				pms->log(MSG_DEBUG, 0, "BUG in update_library(): entity type not implemented by PMS\n");
				break;
		}

		mpd_entity_free(ent);

		++total;
	}

	pms->log(MSG_DEBUG, 0, "Processed a total of %d entities during library update\n", total);

	return get_error_bool();
}
Beispiel #14
0
int main(int argc, char ** argv) {
	struct mpd_connection *conn;

	conn = mpd_connection_new(NULL, 0, 30000);

	if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS)
		return handle_error(conn);

	{
		int i;
		for(i=0;i<3;i++) {
			printf("version[%i]: %i\n",i,
			       mpd_connection_get_server_version(conn)[i]);
		}
	}

	if(argc==1) {
		struct mpd_status * status;
		struct mpd_song *song;
		const struct mpd_audio_format *audio_format;

		mpd_command_list_begin(conn, true);
		mpd_send_status(conn);
		mpd_send_current_song(conn);
		mpd_command_list_end(conn);

		status = mpd_recv_status(conn);
		if (status == NULL)
			return handle_error(conn);

		printf("volume: %i\n", mpd_status_get_volume(status));
		printf("repeat: %i\n", mpd_status_get_repeat(status));
		printf("queue version: %u\n", mpd_status_get_queue_version(status));
		printf("queue length: %i\n", mpd_status_get_queue_length(status));
		if (mpd_status_get_error(status) != NULL)
			printf("error: %s\n", mpd_status_get_error(status));

		if (mpd_status_get_state(status) == MPD_STATE_PLAY ||
		    mpd_status_get_state(status) == MPD_STATE_PAUSE) {
			printf("song: %i\n", mpd_status_get_song_pos(status));
			printf("elaspedTime: %i\n",mpd_status_get_elapsed_time(status));
			printf("elasped_ms: %u\n", mpd_status_get_elapsed_ms(status));
			printf("totalTime: %i\n", mpd_status_get_total_time(status));
			printf("bitRate: %i\n", mpd_status_get_kbit_rate(status));
		}

		audio_format = mpd_status_get_audio_format(status);
		if (audio_format != NULL) {
			printf("sampleRate: %i\n", audio_format->sample_rate);
			printf("bits: %i\n", audio_format->bits);
			printf("channels: %i\n", audio_format->channels);
		}

		mpd_status_free(status);

		if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS)
			return handle_error(conn);

		mpd_response_next(conn);

		while ((song = mpd_recv_song(conn)) != NULL) {
			printf("uri: %s\n", mpd_song_get_uri(song));
			print_tag(song, MPD_TAG_ARTIST, "artist");
			print_tag(song, MPD_TAG_ALBUM, "album");
			print_tag(song, MPD_TAG_TITLE, "title");
			print_tag(song, MPD_TAG_TRACK, "track");
			print_tag(song, MPD_TAG_NAME, "name");
			print_tag(song, MPD_TAG_DATE, "date");

			if (mpd_song_get_duration(song) > 0) {
				printf("time: %u\n", mpd_song_get_duration(song));
			}

			printf("pos: %u\n", mpd_song_get_pos(song));

			mpd_song_free(song);
		}

		if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS ||
		    !mpd_response_finish(conn))
			return handle_error(conn);
	}
	else if(argc==3 && strcmp(argv[1],"lsinfo")==0) {
		struct mpd_entity * entity;

		if (!mpd_send_list_meta(conn, argv[2]))
			return handle_error(conn);

		while ((entity = mpd_recv_entity(conn)) != NULL) {
			const struct mpd_song *song;
			const struct mpd_directory *dir;
			const struct mpd_playlist *pl;

			switch (mpd_entity_get_type(entity)) {
			case MPD_ENTITY_TYPE_UNKNOWN:
				break;

			case MPD_ENTITY_TYPE_SONG:
				song = mpd_entity_get_song(entity);
				printf("uri: %s\n", mpd_song_get_uri(song));
				print_tag(song, MPD_TAG_ARTIST, "artist");
				print_tag(song, MPD_TAG_ALBUM, "album");
				print_tag(song, MPD_TAG_TITLE, "title");
				print_tag(song, MPD_TAG_TRACK, "track");
				break;

			case MPD_ENTITY_TYPE_DIRECTORY:
				dir = mpd_entity_get_directory(entity);
				printf("directory: %s\n", mpd_directory_get_path(dir));
				break;

			case MPD_ENTITY_TYPE_PLAYLIST:
				pl = mpd_entity_get_playlist(entity);
				printf("playlist: %s\n",
				       mpd_playlist_get_path(pl));
				break;
			}

			mpd_entity_free(entity);
		}

		if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS ||
		    !mpd_response_finish(conn))
			return handle_error(conn);
	}
	else if(argc==2 && strcmp(argv[1],"artists")==0) {
		struct mpd_pair *pair;

		if (!mpd_search_db_tags(conn, MPD_TAG_ARTIST) ||
		    !mpd_search_commit(conn))
			return handle_error(conn);

		while ((pair = mpd_recv_pair_tag(conn,
						 MPD_TAG_ARTIST)) != NULL) {
			printf("%s\n", pair->value);
			mpd_return_pair(conn, pair);
		}

		if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS ||
		    !mpd_response_finish(conn))
			return handle_error(conn);
	} else if (argc == 2 && strcmp(argv[1], "playlists") == 0) {
		if (!mpd_send_list_playlists(conn))
			return handle_error(conn);

		struct mpd_playlist *playlist;
		while ((playlist = mpd_recv_playlist(conn)) != NULL) {
			printf("%s\n",
			       mpd_playlist_get_path(playlist));
			mpd_playlist_free(playlist);
		}

		if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS ||
		    !mpd_response_finish(conn))
			return handle_error(conn);
	} else if (argc == 2 && strcmp(argv[1], "idle") == 0) {
		enum mpd_idle idle = mpd_run_idle(conn);
		if (idle == 0 &&
		    mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS)
			return handle_error(conn);

		for (unsigned j = 0;; ++j) {
			enum mpd_idle i = 1 << j;
			const char *name = mpd_idle_name(i);

			if (name == NULL)
				break;

			if (idle & i)
				printf("%s\n", name);
		}
	} else if (argc == 3 && strcmp(argv[1], "subscribe") == 0) {
		/* subscribe to a channel and print all messages */

		if (!mpd_run_subscribe(conn, argv[2]))
			return handle_error(conn);

		while (mpd_run_idle_mask(conn, MPD_IDLE_MESSAGE) != 0) {
			if (!mpd_send_read_messages(conn))
				return handle_error(conn);

			struct mpd_message *msg;
			while ((msg = mpd_recv_message(conn)) != NULL) {
				printf("%s\n", mpd_message_get_text(msg));
				mpd_message_free(msg);
			}

			if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS ||
			    !mpd_response_finish(conn))
				return handle_error(conn);
		}

		return handle_error(conn);
	} else if (argc == 2 && strcmp(argv[1], "channels") == 0) {
		/* print a list of channels */

		if (!mpd_send_channels(conn))
			return handle_error(conn);

		struct mpd_pair *pair;
		while ((pair = mpd_recv_channel_pair(conn)) != NULL) {
			printf("%s\n", pair->value);
			mpd_return_pair(conn, pair);
		}

		if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS ||
		    !mpd_response_finish(conn))
			return handle_error(conn);
	} else if (argc == 4 && strcmp(argv[1], "message") == 0) {
		/* send a message to a channel */

		if (!mpd_run_send_message(conn, argv[2], argv[3]))
			return handle_error(conn);
	}

	mpd_connection_free(conn);

	return 0;
}