Code Monkey home page Code Monkey logo

snapcast-autoconfig's Introduction

snapcast-autoconfig

snapcast-autoconfig watches pre-defined streams on a snapcast server. If any of them are playing, it will then ensure that a group with the configured clients is playing that stream (and can optionally manipulate the volume of each client within that group).

Wait, why is this necessary / useful?

Well, maybe it's better to just explain how I use it. I have multiple room in my house that have speakers I'd like to listen to:

  • Living Room
  • Kitchen
  • Office
  • Bedroom
  • Bathroom
  • Deck

But, there are actually additional logical groupings of those speakers that are useful:

  • "Great Room" (Kitchen + Living Room)
  • "Master Suite" (Bedroom + Bathroom)
  • "Great Room + Outside" (Kitchen + Living Room + Deck ... in the summer!)
  • "Whole House"
  • "Whole House + Outside"

And what's more, I want these speakers and these zones to be available as Airplay targets! Me and mine like to use Airplay to play our music, because it's convenient and most people we know have iPhones. And we don't want to tell people "Oh wait, let me re-configure the sound server"... we want it to just happen automatically.

To solve this problem, I run multiple instances of shairport-sync on my server, each one for a different speaker or logical zone (eg: I have an "Office" stream, a "Kitchen" stream... and also a "Whole House" stream, etc). And, I have snapcast set up to source music from each one of these airplay streams (shairport-sync instances). This brings us to the why of snapcast-autoconfig: it watches snapcast to see if any of these airplay streams become active, and then does the re-grouping of the clients behind the scenes.

All so that we can just say "airplay to the Great Room, mom!" when we're playing music at home.

Believe it or not, it actually works pretty well.

Requirements

  • Ruby >= 2.7.2 (I have tested with 2.7.2 and 3.0.0).
  • A valid configuration file describing the streams to monitor, and the clients that should follow them. See the example in the repo.
  • Your snapcast server must have the TCP api exposed and available (it is, by default).

Installation

bundle install

Deployment / Operation

I manually install this on my server, and have set up a systemd service to run it. I've included an example systemd unit file. My own personal config file is also provided, and can be used as a reference.

FAQ

  • Does it do x/y/z? Probably not, but PRs are welcome!
  • Couldn't you just use the 'meta' stream type? Almost!! Snapcast doesn't allow you to define "home" (or "default", or "initial") groups for clients; and that's still useful and important.
  • Wait, couldn't you just use the pre/post-play scripts in shairport-sync? Yes, actually, but I didn't know about them when I first started the project and now I kinda like this.
  • Hold on, wouldn't Airplay2 make this obsolete? Yes, basically. That'd be really nice to be honest. Hopefully someone cracks it eventually.
  • You just put your personal config into git?! I'm lazy, and the info is not sensitive. It's also an instructive example of how I use it!
  • There are bugs!! I'm not surprised - help me fix them! I've really only tested this at my house!
  • Didn't this used to be written in nodejs? Yes, but that was a bad move on my part; I know ruby a lot better. I just didn't know much about Ruby event-loop programming at the time and node was an easy quick fix.
  • lib/snapcast looks like it could do a lot more than what it does... More of a comment than a question, but you're right: the makings of a full snapcast client are in there.
  • I need help! Please open an issue, and I'll try to help if possible.

snapcast-autoconfig's People

Contributors

ahayworth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

snapcast-autoconfig's Issues

TODO: Write better documentation

This actually works pretty well for me, but the README is snarky and not helpful. We should re-write it to actually better describe what this does and how to use it.

When clients are in an Idle group and one client's preferred stream starts, both clients play it

os: Arch linux
snapclient: 0.25.0
snapserver: 0.25.0

First off, I realise this is a side-effect of how Snapcast works when removing clients from groups ;)

In this scenario:

  • there are two clients c1 and c2
  • each client has its own preferred stream (s1, s2)
  • a "party" stream s0 is lower priority and plays to both s1 and s2

To repro:

  • Play s0 such that c1 and c2 form a playing group g0.
  • Pause s0 -> c1 and c2 remain in g0 which is Idle
  • Play s1 -> the group splits

Result:

  • c1 is in group g1 playing s1
  • c2 is in group g2 playing s1 <-- DOH!

Expected:

  • c2 remains in group g0 which is Idle

Config:

---
server: tcp://localhost:1705
streams:
  Canard:
    clients:
      - canard
  Kitchen:
    clients:
      - kitchen
  Party 1:
    clients:
      - canard
      - kitchen

The result is the same even with more clients in g0. All clients end up in individual groups playing s1.
log.txt

I don't like how the group configuration / selection works, really

This script is highly specific to how I run my home audio system, but it could be a lot more flexible. The configuration file should express three concepts:

  • Streams to watch
  • Clients to care about
  • Rules

That would allow us to build a more flexible system, and specify what to do for undefined situations (eg: if a group exists with a configured client but doesn't match a rule, what should be done? Leave it alone? Forcibly move it? To where? etc).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.