X-Git-Url: http://nitlanguage.org diff --git a/lib/mpd.nit b/lib/mpd.nit index 4c74554..b0d25d8 100644 --- a/lib/mpd.nit +++ b/lib/mpd.nit @@ -14,32 +14,40 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Client for a MPD server +# Music Player Daemon client library module mpd import socket # Connection to a MPD server class MPDConnection - var socket: nullable Socket = null + # 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 Socket = null + var p: nullable TCPStream = null - p = new Socket.stream_with_host(host, port) - p.connect + p = new TCPStream.connect(host, port) + assert p.connected sys.nanosleep(0,5000) - var rep = p.read + var rep = p.read(1024) assert not rep.is_empty if not rep.has_prefix("OK") then print "MPD responded {rep}" @@ -50,19 +58,23 @@ class MPDConnection var password = password if password != null then - write("password {password}\n") + write_and_check("password {password}\n") end end # Write a command to the MPD server - protected fun write(msg: String) + protected fun write_and_check(msg: String) do if socket == null then connect socket.write(msg) sys.nanosleep(0,5000) - var rep = socket.read - assert rep.has_prefix("OK") else print "MPD responded {rep}" + 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 @@ -72,27 +84,37 @@ class MPDConnection 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 + 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.index_of(' ') + 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 == "volume:" then + 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 - return new ServerStatus(volume, state) + var status = new ServerStatus(volume, state, elapsed, time_at, time_total) + return status else return null end @@ -108,7 +130,7 @@ class MPDConnection var vol = status.volume if vol != null then var new_vol = vol + diff - new_vol = new_vol.max(0).min(100) + new_vol = new_vol.clamp(0, 100) volume = new_vol return end @@ -117,16 +139,17 @@ class MPDConnection error = "Cannot get volume" end - fun volume=(vol: Int) do write("setvol {vol}\n") + # 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("pause\n") + fun pause do write_and_check("pause\n") # Stop music playing on the MPD server - fun stop do write("stop\n") + fun stop do write_and_check("stop\n") # Play music playing on the MPD server - fun play do write("play\n") + fun play do write_and_check("play\n") # Get information on the currently playing song on the MPD server fun current_song: nullable SongInfo @@ -136,14 +159,15 @@ class MPDConnection 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 + 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.index_of(' ') + var first_space = l.chars.index_of(' ') var rest = l.substring_from(first_space+1) if key == "album:" then album = rest @@ -151,27 +175,83 @@ class MPDConnection 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 then - return new SongInfo(album, artist, title) + 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