E_NO_SUCH_BLOG

Programming, philosophy, pedaling.


Muzak, Week 5

Jan 2, 2017

Tags: programming, ruby, muzak

Preword: This is the fifth weekly post on muzak’s development. You can find the rest under the muzak tag. It might also be the last (regular) post in the series, since muzak is increasingly stable and most of my “development” has shifted towards custom plugins and commands for my own convenience.

I did a little bit more work than I expected to this week, so here’s an update post.

Quick statistics, as usual:

Big(ger) changes

Two-way muzakd communication via sockets

muzakd now uses a TCP socket instead of a FIFO, which presents two major advantages:

By default muzakd runs on localhost port 2669, but this can be changed by setting daemon-port and/or daemon-host in ~/.config/muzak/muzak.yml.

Command responses

Piggybacking on the new TCP socket above is command responses, which provide a standard response structure for muzak commands.

Command responses are always ruby hashes, which muzakd handily serializes into JSON for clients to consume. For example, here’s muzak-cmd invocation:

$ muzak-cmd now-playing > response.json

response.json then contains something like this (pretty-printed):

{
   "response" : {
      "data" : {
         "playing" : "HiiiPower by Kendrick Lamar on Section.80"
      },
      "method" : "now_playing",
      "error" : null
   }
}

These responses are easily constructed using Utils#build_response:

module Muzak
  module Cmd
    def do_something
      build_response data: {
      	message: "I lied, this command doesn't really do anything"
      }
    end
  end
end

Command documentation

Complementing the new response system is full user documentation of commands (including descriptions, syntax, and examples) via COMMANDS.md.

This file gets included in YARD, yielding a pretty page in the online documentation.

Better command and argument handling

Previously, muzak “handled” command arguments by passing them as a variable argument list (*args) and letting each individual command figure them out for themselves. This resulted in a bunch of unnecessary boilerplate and ugly guard methods like warn_arity and fail_arity.

This has been replaced with arity checking in Muzak::Instance#command. When the number of arguments provided doesn’t match the command’s arity, a helpful error response is returned:

$ muzak-cmd playlist-add-artist | json_pp
{
   "response" : {
      "error" : "wrong number of arguments (given 0, expected 1+)"
   }
}

Similarly, Muzak::Instance#method_missing has been removed in favor of a check against Muzak::Cmd.commands.

Small(er) changes

Performance improvements

There are lots of small improvements to muzak’s performance in this week’s changes. In particular:

Deprecation of bin/muzak

I basically haven’t used bin/muzak since the first week of muzak’s development. As such, I mostly ignored it while making UI/UX decisions. This has culminated in it being mostly useless now that all commands return response hashes (instead of printing useful output, as they originally did).

I’ve removed bin/muzak from the Gem specification, and I’ll probably remove it from the repository entirely shortly.

As always, thanks for reading!

- William

P.S.: I haven’t been keeping track of development statistics or pace in the other muzak repositories (namely muzak-utils, muzak-commands, and muzak-plugins). They’re all worth taking a look at if you want to augment your muzak flow.