Music Player Daemon client library

Introduced classes

class MPDConnection

mpd :: MPDConnection

Connection to a MPD server
class ServerStatus

mpd :: ServerStatus

MPD server status
class SongInfo

mpd :: SongInfo

MPD song info

All class definitions

class MPDConnection

mpd $ MPDConnection

Connection to a MPD server
class ServerStatus

mpd $ ServerStatus

MPD server status
class SongInfo

mpd $ SongInfo

MPD song info
package_diagram mpd::mpd mpd socket socket mpd::mpd->socket core core socket->core ...core ... ...core->core a_star-m a_star-m a_star-m->mpd::mpd

Ancestors

module abstract_collection

core :: abstract_collection

Abstract collection classes and services.
module abstract_text

core :: abstract_text

Abstract class for manipulation of sequences of characters
module array

core :: array

This module introduces the standard array structure.
module bitset

core :: bitset

Services to handle BitSet
module bytes

core :: bytes

Services for byte streams and arrays
module circular_array

core :: circular_array

Efficient data structure to access both end of the sequence.
module codec_base

core :: codec_base

Base for codecs to use with streams
module codecs

core :: codecs

Group module for all codec-related manipulations
module collection

core :: collection

This module define several collection classes.
module core

core :: core

Standard classes and methods used by default by Nit programs and libraries.
module environ

core :: environ

Access to the environment variables of the process
module error

core :: error

Standard error-management infrastructure.
module exec

core :: exec

Invocation and management of operating system sub-processes.
module file

core :: file

File manipulations (create, read, write, etc.)
module fixed_ints

core :: fixed_ints

Basic integers of fixed-precision
module fixed_ints_text

core :: fixed_ints_text

Text services to complement fixed_ints
module flat

core :: flat

All the array-based text representations
module gc

core :: gc

Access to the Nit internal garbage collection mechanism
module hash_collection

core :: hash_collection

Introduce HashMap and HashSet.
module iso8859_1

core :: iso8859_1

Codec for ISO8859-1 I/O
module kernel

core :: kernel

Most basic classes and methods.
module list

core :: list

This module handle double linked lists
module math

core :: math

Mathematical operations
module native

core :: native

Native structures for text and bytes
module numeric

core :: numeric

Advanced services for Numeric types
module protocol

core :: protocol

module queue

core :: queue

Queuing data structures and wrappers
module range

core :: range

Module for range of discrete objects.
module re

core :: re

Regular expression support for all services based on Pattern
module ropes

core :: ropes

Tree-based representation of a String.
module socket_c

socket :: socket_c

Low-level socket functionalities
module sorter

core :: sorter

This module contains classes used to compare things and sorts arrays.
module stream

core :: stream

Input and output streams of characters
module text

core :: text

All the classes and methods related to the manipulation of text entities
module time

core :: time

Management of time and dates
module union_find

core :: union_find

union–find algorithm using an efficient disjoint-set data structure
module utf8

core :: utf8

Codec for UTF-8 I/O

Parents

module socket

socket :: socket

Socket services

Children

module a_star-m

a_star-m

# Music Player Daemon client library
module mpd

import socket

# Connection to a MPD server
class MPDConnection

	# Socket connection to server.
	var socket: nullable TCPStream = null

	# Server hostname.
	var host: String

	# Server port.
	var port: Int

	# Server password.
	var password: nullable String

	# Last occured error.
	var error: nullable String = null

	# Connect to the MPD server
	fun connect
	do
		var p: nullable TCPStream = null

		p = new TCPStream.connect(host, port)
		assert p.connected

		sys.nanosleep(0,5000)

		var rep = p.read(1024)
		assert not rep.is_empty
		if not rep.has_prefix("OK") then
			print "MPD responded {rep}"
			abort
		end

		socket = p

		var password = password
		if password != null then
			write_and_check("password {password}\n")
		end
	end

	# Write a command to the MPD server
	protected fun write_and_check(msg: String)
	do
		if socket == null then connect

		socket.write(msg)
		sys.nanosleep(0,5000)
		var rep = socket.read(1024)
		if not rep.has_prefix("OK") then
			print "Error: MPD responded {rep}"
			socket.close
			socket = null
		end
	end

	# Get MPD server status
	fun status: nullable ServerStatus
	do
		if socket == null then connect

		var volume: nullable Int = null
		var state: nullable String = null
		var elapsed: nullable Int = null
		var time_at: nullable Int = null
		var time_total: nullable Int = null

		# get current status
		socket.write("status\n")
		var rep = socket.read(1024)
		for l in rep.split_with("\n") do
			var words = l.split_with(" ")
			if words.length > 1 then
				var key = words[0].to_lower
				var first_space = l.chars.index_of(' ')
				var rest = l.substring_from(first_space+1)
				if  key == "volume:" then
					volume = rest.to_i
					if volume == -1 then volume = null
				else if  key == "state:" then
					state = rest
				else if  key == "elapsed:" then
					elapsed = rest.to_i
				else if  key == "time:" then
					var times = rest.split(":")
					time_at = times[0].to_i
					time_total = times[1].to_i
				end
			end
		end

		if state != null then
			var status = new ServerStatus(volume, state, elapsed, time_at, time_total)
			return status
		else
			return null
		end
	end

	# Set the volume relatively
	fun relative_volume=(diff: Int)
	do
		if socket == null then connect

		var status = status
		if status != null then
			var vol = status.volume
			if vol != null then
				var new_vol = vol + diff
				new_vol = new_vol.clamp(0, 100)
				volume = new_vol
				return
			end
		end

		error = "Cannot get volume"
	end

	# Set MPD server volume.
	fun volume=(vol: Int) do write_and_check("setvol {vol}\n")

	# Pause music playing on the MPD server
	fun pause do write_and_check("pause\n")

	# Stop music playing on the MPD server
	fun stop do write_and_check("stop\n")

	# Play music playing on the MPD server
	fun play do write_and_check("play\n")

	# Get information on the currently playing song on the MPD server
	fun current_song: nullable SongInfo
	do
		if socket == null then connect

		var album: nullable String = null
		var artist: nullable String = null
		var title: nullable String = null
		var time: nullable Int = null

		socket.write("currentsong\n")
		var rep = socket.read(1024)
		for l in rep.split_with("\n") do
			var words = l.split_with(" ")
			if words.length > 1 then
				var key = words[0].to_lower
				var first_space = l.chars.index_of(' ')
				var rest = l.substring_from(first_space+1)
				if key == "album:" then
					album = rest
				else if key == "artist:" then
					artist = rest
				else if key == "title:" then
					title = rest
				else if key == "time:" then
					time = rest.to_i
				end
			end
		end

		if album != null and artist != null and
			title != null and time != null then
			return new SongInfo(album, artist, title, time)
		else
			return null
		end
	end

	# Load playlist named `name`.
	fun load_playlist(name: String)
	do
		write_and_check "load \"{name}\""
	end
end

# MPD song info
class SongInfo
	# Song album.
	var album: String

	# Song artist.
	var artist: String

	# Song title.
	var title: String

	# Song total duration.
	var time: Int
end

# MPD server status
class ServerStatus

	# MPD server volume.
	var volume: nullable Int

	# Playback state (play/stop/pause).
	var state: String

	# Is MPD server playing?
	fun playing: Bool do return state == "play"

	# Is MPD server stopped?
	fun stopped: Bool do return state == "stop"

	# Time elapsed within the current song.
	var elapsed: nullable Int

	# TODO comment
	var time_at: nullable Int

	# Total time of the current song.
	var time_total: nullable Int

	# Get the cursor position on the song duration.
	fun time_ratio: nullable Float do
		if time_at == null or time_total == null then return null
		return time_at.to_f / time_total.to_f
	end

	redef fun to_s do
		var vol = "unknown"
		if volume != null then vol = volume.to_s

		var time_at = time_at
		var time_total = time_total
		var elapsed = elapsed
		if time_at != null and time_total != null and elapsed != null then
			return "volume: {vol}\nstate: {state}\nelapsed: {elapsed}\ntime_[at|total]: {time_at}:{time_total}\ntime_ratio: {time_ratio.as(not null)}"
		else
			return "volume: {vol}\nstate: {state}"
		end
	end
end
lib/mpd/mpd.nit:17,1--257,3