Switch to side-by-side view

--- a/scctl_src/scctl.cpp
+++ b/scctl_src/scctl.cpp
@@ -26,7 +26,9 @@
  * 
  * To avoid encurring a discovery timeout for each op, there is a
  * server mode, in which a permanent process executes the above
- * commands, received on Unix socket, and returns the results.
+ * commands, received on Unix socket, and returns the results. The
+ * Unix socket name is based on the uid, so there is one per active
+ * user.
  *
  * When executing any of the ops from the command line, the program
  * first tries to contact the server, and does things itself if no
@@ -59,6 +61,12 @@
 using namespace UPnPP;
 using namespace std;
 using namespace Songcast;
+
+#ifdef LIBUPNPP_VERSION_MAJOR
+#if LIBUPNPP_AT_LEAST(0,16,0)
+#define HAVE_SETSOURCEINDEX_IN_LINN
+#endif
+#endif
 
 #define OPT_L 0x1
 #define OPT_S 0x2
@@ -119,6 +127,40 @@
     return out.str();
 }
 
+int dosomething(int opflags, const vector<string>& args, string& out)
+{
+    if (opflags & OPT_l) {
+        out = showReceivers(opflags);
+    } else if (opflags & OPT_L) {
+        out = showSenders(opflags);
+    } else if (opflags & OPT_r) {
+        if (args.size() < 2)
+            return 1;
+        setReceiversFromSender(args[0], vector<string>(args.begin() + 1,
+                                                       args.end()));
+    } else if (opflags & OPT_s) {
+        if (args.size() < 2)
+            return 1;
+        setReceiversFromSender(args[0], vector<string>(args.begin() + 1,
+                                                       args.end()));
+    } else if (opflags & OPT_x) {
+        if (args.size() < 1)
+            return 1;
+        stopReceivers(args);
+#ifdef HAVE_SETSOURCEINDEX_IN_LINN
+    } else if ((opflags & OPT_i)) {
+        if (args.size() < 2)
+            return 1;
+        setSourceIndex(args[0], std::stoi(args[1]));
+    } else if ((opflags & OPT_I)) {
+        if (args.size() < 2)
+            return 1;
+        setSourceIndexByName(args[0], args[1]);
+#endif
+    }
+    return 0;
+}
+
 static char *thisprog;
 static char usage [] =
 " -l List renderers with Songcast Receiver capability\n"
@@ -126,8 +168,10 @@
 "   -m : for above modes: use parseable format\n"
 "For the following options the renderers can be designated by their \n"
 "uid (safer) or friendly name\n"
+#ifdef HAVE_SETSOURCEINDEX_IN_LINN
 " -i <renderer> i : set source index\n"
 " -I <renderer> name : set source index by name\n"
+#endif
 " -s <master> <slave> [slave ...] : Set up the slaves renderers as Songcast\n"
 "    Receivers and make them play from the same uri as the master receiver\n"
 " -x <renderer> [renderer ...] Reset renderers from Songcast to Playlist\n"
@@ -165,41 +209,22 @@
         switch (ret) {
         case 'f': op_flags |= OPT_f; break;
         case 'h': Usage(stdout); break;
-        case 'l':
-            op_flags |= OPT_l;
-            break;
-        case 'L':
-            op_flags |= OPT_L;
-            break;
-        case 'm':
-            op_flags |= OPT_m;
-            break;
-        case 'r':
-            op_flags |= OPT_r;
-            break;
-        case 's':
-            op_flags |= OPT_s;
-            break;
-        case 'S':
-            op_flags |= OPT_S;
-            break;
-        case 'x':
-            op_flags |= OPT_x;
-            break;
-        case 'i':
-            op_flags |= OPT_i;
-            break;
-        case 'I':
-            op_flags |= OPT_I;
-            break;
+        case 'l': op_flags |= OPT_l; break;
+        case 'L': op_flags |= OPT_L; break;
+        case 'm': op_flags |= OPT_m; break;
+        case 'r': op_flags |= OPT_r; break;
+        case 's': op_flags |= OPT_s; break;
+        case 'S': op_flags |= OPT_S; break;
+        case 'x': op_flags |= OPT_x; break;
+        case 'i': op_flags |= OPT_i; break;
+        case 'I': op_flags |= OPT_I; break;
         default: Usage();
         }
     }
-    //fprintf(stderr, "argc %d optind %d flgs: 0x%x\n", argc, optind, op_flags);
-
-    // If we're not a server, try to contact one to avoid the
-    // discovery timeout
-    if (!(op_flags & OPT_S) && tryserver(op_flags, argc -optind, 
+
+    // If we're not to become a server, try to contact one to avoid
+    // the discovery timeout
+    if (!(op_flags & OPT_S) && tryserver(op_flags, argc - optind, 
                                          &argv[optind])) {
         exit(0);
     }
@@ -208,6 +233,8 @@
     if ((op_flags & ~(OPT_f|OPT_m)) == 0)
         Usage();
 
+    // Logger::getTheLog("stderr")->setLogLevel(Logger::LLDEB0);
+
     LibUPnP *mylib = LibUPnP::getLibUPnP();
     if (!mylib) {
         cerr << "Can't get LibUPnP" << endl;
@@ -224,43 +251,15 @@
     while (optind < argc) {
         args.push_back(argv[optind++]);
     }
-    
-    if ((op_flags & OPT_l)) {
-        if (args.size())
-            Usage();
-        string out = showReceivers(op_flags);
-        cout << out;
-    } else if ((op_flags & OPT_L)) {
-        if (args.size())
-            Usage();
-        string out = showSenders(op_flags);
-        cout << out;
-    } else if ((op_flags & OPT_r)) {
-        if (args.size() < 2)
-            Usage();
-        setReceiversFromSender(args[0], vector<string>(args.begin() + 1,
-                                                       args.end()));
-    } else if ((op_flags & OPT_s)) {
-        if (args.size() < 2)
-            Usage();
-        setReceiversFromReceiver(args[0], vector<string>(args.begin()+1,
-                                                         args.end()));
-    } else if ((op_flags & OPT_x)) {
-        if (args.size() < 1)
-            Usage();
-        stopReceivers(args);
-    } else if ((op_flags & OPT_i)) {
-        if (args.size() < 2)
-            Usage();
-        setSourceIndex(args[0], std::stoi(args[1]));
-    } else if ((op_flags & OPT_I)) {
-        if (args.size() < 2)
-            Usage();
-        setSourceIndexByName(args[0], args[1]);
-    } else if ((op_flags & OPT_S)) {
+
+    if ((op_flags & OPT_S)) {
         exit(runserver());
     } else {
-        Usage();
+        string out;
+        if (dosomething(op_flags, args, out)) {
+            Usage();
+        }
+        cout << out;
     }
 
     // If we get here, we have executed a local command. If -f is set,
@@ -274,6 +273,7 @@
     return 0;
 }
 
+
 // The Unix socket path which we use for client-server operation
 bool sockname(string& nm)
 {
@@ -335,18 +335,23 @@
     return true;
 }
 
-bool tryserver(int opflags, int argc, char **argv)
+static vector<string> argvtov(char *argv[])
+{
+    vector<string> out;
+    while (argv && *argv) {
+        out.push_back(*argv++);
+    }
+    return out;
+}
+
+bool tryserver(int opflags, int argc, char *argv[])
 {
     char opts[30];
     sprintf(opts, "0x%x", opflags);
     string cmd(opts);
     cmd += " ";
-        
-    for (int i = 0; i < argc; i++) {
-        // May need quoting here ? 
-        cmd  += argv[i]; 
-        cmd += " ";
-    }
+    vector<string> va = argvtov(argv);
+    cmd += stringsToString(va);
     cmd += "\n";
     return tryserver(cmd);
 }
@@ -374,68 +379,31 @@
     // Get command
     string line;
     {
-        char buf[2048];
-        if  (con->getline(buf, 2048, 2) <= 0) {
+        const int LL(10240);
+        char buf[LL];
+        if  (con->getline(buf, LL, 2) <= 0) {
             LOGERR("scctl: server: getline() failed\n");
             return 1;
         }
         line = buf;
     }
-
     trimstring(line, " \n");
-
     LOGDEB1("scctl: server: got cmd: " << line << endl);
 
-    vector<string> toks;
-    stringToTokens(line, toks);
-    if (toks.empty()) {
-        return 1;
-    }
-
-    int opflags = strtoul(toks[0].c_str(), 0, 0);
-
+    vector<string> args;
+    stringToStrings(line, args);
+    if (args.empty()) {
+        return 1;
+    }
+
+    int opflags = strtoul(args[0].c_str(), 0, 0);
+    args.erase(args.begin());
     string out;
     if (opflags & OPT_p) {
         // ping
         out = "Ok\n";
-    } else if (opflags & OPT_l) {
-        out = showReceivers(opflags);
-    } else if (opflags & OPT_L) {
-        out = showSenders(opflags);
-    } else if (opflags & OPT_s) {
-        if (toks.size() < 3)
-            return 1;
-        vector<string>::iterator beg = toks.begin();
-        beg++;
-        string master = *beg;
-        beg++;
-        vector<string> slaves(beg, toks.end());
-        ReceiverState mst;
-        getReceiverState(master, mst);
-        for (auto it = slaves.begin(); it != slaves.end(); it++) {
-            ReceiverState st;
-            getReceiverState(*it, st);
-            setReceiverPlaying(st, mst.uri, mst.meta);
-        }
-    } else if (opflags & OPT_x) {
-        if (toks.size() < 2)
-            return 1;
-        vector<string>::iterator beg = toks.begin();
-        beg++;
-        vector<string> slaves(beg, toks.end());
-        stopReceivers(slaves);
-    } else if (opflags & OPT_r) {
-        if (toks.size() < 3)
-            return 1;
-        vector<string>::iterator beg = toks.begin();
-        beg++;
-        string sender = *beg;
-        beg++;
-        vector<string> receivers(beg, toks.end());
-        setReceiversFromSender(sender, receivers);
     } else {
-        LOGERR("scctl: server: bad cmd:" << toks[0] << endl);
-        return 1;
+        dosomething(opflags, args, out);
     }
 
     if (con->send(out.c_str(), out.size(), 0) < 0) {