+
+ res = get_address(&config->broadcast, &pref, &sockname);
+ if(!res) exit(-1);
+ if(config->broadcast_from.n) {
+ sres = get_address(&config->broadcast_from, &prefbind, &ssockname);
+ if(!sres) exit(-1);
+ } else
+ sres = 0;
+ if((bfd = socket(res->ai_family,
+ res->ai_socktype,
+ res->ai_protocol)) < 0)
+ fatal(errno, "error creating broadcast socket");
+ if(setsockopt(bfd, SOL_SOCKET, SO_BROADCAST, &one, sizeof one) < 0)
+ fatal(errno, "error setting SO_BROADCAST on broadcast socket");
+ len = sizeof sndbuf;
+ if(getsockopt(bfd, SOL_SOCKET, SO_SNDBUF,
+ &sndbuf, &len) < 0)
+ fatal(errno, "error getting SO_SNDBUF");
+ if(target_sndbuf > sndbuf) {
+ if(setsockopt(bfd, SOL_SOCKET, SO_SNDBUF,
+ &target_sndbuf, sizeof target_sndbuf) < 0)
+ error(errno, "error setting SO_SNDBUF to %d", target_sndbuf);
+ else
+ info("changed socket send buffer size from %d to %d",
+ sndbuf, target_sndbuf);
+ } else
+ info("default socket send buffer is %d",
+ sndbuf);
+ /* We might well want to set additional broadcast- or multicast-related
+ * options here */
+ if(sres && bind(bfd, sres->ai_addr, sres->ai_addrlen) < 0)
+ fatal(errno, "error binding broadcast socket to %s", ssockname);
+ if(connect(bfd, res->ai_addr, res->ai_addrlen) < 0)
+ fatal(errno, "error connecting broadcast socket to %s", sockname);
+ /* Select an SSRC */
+ gcry_randomize(&rtp_id, sizeof rtp_id, GCRY_STRONG_RANDOM);
+ info("selected network backend, sending to %s", sockname);
+ if(config->sample_format.byte_format != AO_FMT_BIG) {
+ info("forcing big-endian sample format");
+ config->sample_format.byte_format = AO_FMT_BIG;
+ }
+}
+
+/** @brief Structure of a backend */
+struct speaker_backend {
+ /** @brief Which backend this is
+ *
+ * @c -1 terminates the list.
+ */
+ int backend;
+
+ /** @brief Initialization
+ *
+ * Called once at startup.
+ */
+ void (*init)(void);
+};
+
+/** @brief Selected backend */
+static const struct speaker_backend *backend;
+
+/** @brief Table of speaker backends */
+static const struct speaker_backend backends[] = {
+#if API_ALSA
+ {
+ BACKEND_ALSA,
+ alsa_init
+ },
+#endif
+ {
+ BACKEND_COMMAND,
+ command_init
+ },
+ {
+ BACKEND_NETWORK,
+ network_init
+ },
+ { -1, 0 }
+};
+
+int main(int argc, char **argv) {
+ int n, fd, stdin_slot, alsa_slots, cmdfd_slot, bfd_slot, poke, timeout;
+ struct track *t;
+ struct speaker_message sm;