{ "pause-mode", required_argument, 0, 'P' },
{ "socket", required_argument, 0, 's' },
{ "config", required_argument, 0, 'C' },
+ { "user-config", required_argument, 0, 'u' },
{ "monitor", no_argument, 0, 'M' },
{ 0, 0, 0, 0 }
};
" --min, -m FRAMES Buffer low water mark\n"
" --max, -x FRAMES Buffer maximum size\n"
" --rcvbuf, -R BYTES Socket receive buffer size\n"
- " --config, -C PATH Set configuration file\n"
+ " --config, -C PATH Set system configuration file\n"
+ " --user-config, -u PATH Set user configuration file\n"
" --api, -A API Select audio API. Possibilities:\n"
" ");
int first = 1;
return samples;
}
-static int compare_family(const struct ifaddrs *a,
- const struct ifaddrs *b,
- int family) {
- int afamily = a->ifa_addr->sa_family;
- int bfamily = b->ifa_addr->sa_family;
- if(afamily != bfamily) {
- /* Preferred family wins */
- if(afamily == family) return 1;
- if(bfamily == family) return -1;
- /* Either there's no preference or it doesn't help. Prefer IPv4 */
- if(afamily == AF_INET) return 1;
- if(bfamily == AF_INET) return -1;
- /* Failing that prefer IPv6 */
- if(afamily == AF_INET6) return 1;
- if(bfamily == AF_INET6) return -1;
- }
- return 0;
-}
-
-static int compare_flags(const struct ifaddrs *a,
- const struct ifaddrs *b) {
- unsigned aflags = a->ifa_flags, bflags = b->ifa_flags;
- /* Up interfaces are better than down ones */
- unsigned aup = aflags & IFF_UP, bup = bflags & IFF_UP;
- if(aup != bup)
- return aup > bup ? 1 : -1;
-#if IFF_DYNAMIC
- /* Static addresses are better than dynamic */
- unsigned adynamic = aflags & IFF_DYNAMIC, bdynamic = bflags & IFF_DYNAMIC;
- if(adynamic != bdynamic)
- return adynamic < bdynamic ? 1 : -1;
-#endif
- unsigned aloopback = aflags & IFF_LOOPBACK, bloopback = bflags & IFF_LOOPBACK;
- /* Static addresses are better than dynamic */
- if(aloopback != bloopback)
- return aloopback < bloopback ? 1 : -1;
- return 0;
-}
-
-static int compare_interfaces(const struct ifaddrs *a,
- const struct ifaddrs *b,
- int family) {
- int c;
- if((c = compare_family(a, b, family))) return c;
- return compare_flags(a, b);
-}
-
int main(int argc, char **argv) {
int n, err;
struct addrinfo *res;
logdate = 1;
mem_init();
if(!setlocale(LC_CTYPE, "")) disorder_fatal(errno, "error calling setlocale");
- while((n = getopt_long(argc, argv, "hVdD:m:x:L:R:aocC:re:P:MA:", options, 0)) >= 0) {
+ while((n = getopt_long(argc, argv, "hVdD:m:x:L:R:aocC:u:re:P:MA:", options, 0)) >= 0) {
switch(n) {
case 'h': help();
case 'V': version("disorder-playrtp");
#endif
case 'A': backend = uaudio_find(optarg); break;
case 'C': configfile = optarg; break;
+ case 'u': userconfigfile = optarg; break;
case 's': control_socket = optarg; break;
case 'r': dumpfile = optarg; break;
case 'e': backend = &uaudio_command; uaudio_set("command", optarg); break;
if(!(c = disorder_new(1))) exit(EXIT_FAILURE);
if(disorder_connect(c)) exit(EXIT_FAILURE);
}
- /* If no address was given, pick something sensible based on the known-
- * working connectivity to the server */
+ /* If no address was given, we need to pick one. But we already have a
+ * connection to the server, so we can probably use the address from that.
+ */
+ struct sockaddr_storage ss;
if(!node) {
- int family = config->rtp_request_address.af;
- if(family == AF_UNSPEC) family = disorder_client_af(c);
- /* Get a list of interfaces */
- struct ifaddrs *ifa, *bestifa = NULL;
- if(getifaddrs(&ifa) < 0)
- disorder_fatal(errno, "error calling getifaddrs");
- /* Try to pick a good one */
- for(; ifa; ifa = ifa->ifa_next) {
- if(!ifa->ifa_addr) continue;
- if(bestifa == NULL
- || compare_interfaces(ifa, bestifa, family) > 0)
- bestifa = ifa;
- }
- if(!bestifa)
- disorder_fatal(0, "failed to select a network interface");
- sa = bestifa->ifa_addr;
- switch(sa->sa_family) {
- case AF_INET: ((struct sockaddr_in *)sa)->sin_port = 0; break;
- case AF_INET6: ((struct sockaddr_in6 *)sa)->sin6_port = 0; break;
- default: assert(!"unexpected address family");
+ addr_len = sizeof ss;
+ if(disorder_client_sockname(c, (struct sockaddr *)&ss, &addr_len))
+ exit(EXIT_FAILURE);
+ if(ss.ss_family != AF_INET && ss.ss_family != AF_INET6) {
+ /* We're using a Unix-domain socket, so use a loopback address. I'm
+ * cowardly using IPv4 here. */
+ struct sockaddr_in *sin = (struct sockaddr_in *)&ss;
+ sin->sin_family = AF_INET;
+ sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
}
+ sa = (struct sockaddr *)&ss;
prefs.ai_family = sa->sa_family;
}
/* If we have an address or port to resolve then do that now */