xaizek / pms (License: GPLv3+) (since 2018-12-07)
Older version of Practical Music Search written in C++.
<root> / src / mpd.h (6592e1d0e75f4f3563fabda962c9939b33546078) (5,845B) (mode 100644) [raw]
/* vi:set ts=8 sts=8 sw=8 noet:
 *
 * Practical Music Search
 * Copyright (c) 2006-2011  Kim Tore Jensen
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#ifndef _PMS_MPD_H_
#define _PMS_MPD_H_

#include "songlist.h"
#include "song.h"
#include <string>
#include <sys/select.h>

/* MPD error codes */
#define MPD_ERR_NONE 0
#define MPD_ERR_CONNECTION 1
#define MPD_ERR_NOTMPD 2
#define MPD_ERR_ACK 3
#define MPD_ERR_BADPASS 4
#define MPD_ERR_VERSION 5

/* mpd_getline statuses */
#define MPD_GETLINE_ERR -1
#define MPD_GETLINE_ACK -1
#define MPD_GETLINE_OK 0
#define MPD_GETLINE_MORE 1

/* MPD player states */
#define MPD_STATE_UNKNOWN -1
#define MPD_STATE_PLAY 0
#define MPD_STATE_STOP 1
#define MPD_STATE_PAUSE 2

/* IDLE command updates */
enum
{
	MPD_UPDATE_NONE = 0,
	MPD_UPDATE_STATUS = 1 << 0,
	MPD_UPDATE_PLAYLIST = 1 << 1,
	MPD_UPDATE_DB = 1 << 2,
	MPD_UPDATE_LIBRARY = 1 << 3
};

typedef struct
{
	int		volume;
	bool		repeat;
	bool		random;
	bool		single;
	bool		consume;
	long		playlist;
	int		playlistlength;
	int		xfade;
	double		mixrampdb;
	int		mixrampdelay;
	int		state;
	song_t		song;
	song_t		songid;
	song_t		nextsong;
	song_t		nextsongid;
	int		length;
	float		elapsed;
	int		bitrate;
	long		samplerate;
	int		bits;
	int		channels;
}

mpd_status;

typedef struct
{
	song_t			artists;
	song_t			albums;
	song_t			songs;
	unsigned long		uptime;
	unsigned long		playtime;
	unsigned long		db_playtime;
	unsigned long long	db_update;
}

mpd_stats;

typedef enum
{
	REPLAYGAIN_OFF,
	REPLAYGAIN_TRACK,
	REPLAYGAIN_ALBUM
}

replay_gain_mode;

#define PMS_RECV_BUFLEN 50000


using namespace std;

class MPD
{
	private:
		string		host;
		string		port;
		string		password;
		string		buffer;
		char		getbuf[1025];

		string		error;
		int		errno;

		/* Connection variables */
		int		sock;
		bool		connected;
		fd_set		fdset;
		int		protocol_version[3];
		struct timeval	last_update;
		struct timeval	last_clock;
		bool		is_idle;

		/* Has the list been auto-advanced since last song switch? */
		int		autoadvance_playlist;

		/* Advance clock in IDLE mode */
		void		run_clock();

		/* Set/unset idle status */
		bool		set_idle(bool nidle);

		/* Trigger an error. Always returns false. */
		bool		trigerr(int nerrno, const char * format, ...);

		/* Parse the initial connection string from MPD */
		bool		set_protocol_version(string data);

		/* Retrieve a songlist from MPD after a command has been sent, and store it in a Songlist */
		int		recv_songs_to_list(Songlist * slist, void (*) ());

		/* Send a command to MPD, turning IDLE off if needed */
		int		mpd_send(const char * data, ...);

		/* Send a command to MPD */
		int		mpd_raw_send(string data);

		/* Get data from MPD and fetch next line. See MPD_GETLINE_* for return codes */
		int		mpd_getline(string * nextline);

		/* Split a "parameter: value" pair */
		int		split_pair(string * line, string * param, string * value);

		/* Update the current song pointer */
		Song *		update_currentsong();

	public:
		MPD();
		~MPD();

		/* MPD state */
		mpd_status	status;
		mpd_stats	stats;

		/* Server-side lists */
		Songlist	playlist;
		Songlist	library;

		/* Current song. May be NULL. */
		Song *		currentsong;

		/* Current songlist. Never NULL. */
		Songlist *	active_songlist;

		/* Textual representation of play progression */
		string		playstring;

		/* Initialise a connection to an MPD server */
		bool		mpd_connect(string host, string port);

		/* Shut it down, houston. */
		void		mpd_disconnect();

		/* Returns true if there is an active connection. */
		bool		is_connected();

		/* Change password */
		bool		set_password(string password);

		/* Fetch the entire MPD library */
		int		get_library();

		/* Fetch MPD playlist updates since last time */
		int		get_playlist();

		/* Retrieve MPD stats and status */
		int		get_stats();
		int		get_status();

		/* Polls the socket to see if there is any IDLE data to collect. Returns true if there are any updates. */
		int		poll();

		/* Synchronise PMS' play mode config with MPD. */
		int		apply_opts();
		int		read_opts();

		/* Activates a songlist */
		int		activate_songlist(Songlist * list);

		/* List management */
		int		remove(Songlist * list, selection_t selection);
		int		put(Songlist * list, size_t position, selection_t selection);

		/* Returns a pointer to the next song in line according to play mode and config, or NULL if none. */
		Song *		next_song_in_line(int steps = 1);
		Song *		next_auto_song_in_line();

		/* Update textual representation of play progression */
		void		update_playstring();

		/* Update library */
		int		update(string dir);

		/* Playback options */
		int		set_consume(bool nconsume);
		int		set_crossfade(unsigned int nseconds);
		int		set_mixrampdb(int ndecibels);
		int		set_mixrampdelay(int nseconds);
		int		set_random(bool nrandom);
		int		set_repeat(bool nrepeat);
		int		set_volume(unsigned int nvol);
		int		set_single(bool nsingle);
		int		set_replay_gain_mode(replay_gain_mode nrgm);

		/* Player control */
		int		pause(bool npause);
		int		addid(string uri, int position = -1);
		int		playid(int id);
		int		stop();
		int		next();
		int		previous();
		int		seek(int seconds);

};

void update_library_statusbar();

#endif /* _PMS_MPD_H_ */
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/pms

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/pms

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master