chiark / gitweb /
Move ENDIAN_ constants to new byte-order.h.
[disorder] / clients / disorder.c
index b57a8de1f28f5ee2fee953577b1bc452bcf16cd7..48bef78a4e5de07f6b3e9972605a388604129c5e 100644 (file)
@@ -2,20 +2,21 @@
  * This file is part of DisOrder.
  * Copyright (C) 2004-2008 Richard Kettlewell
  *
- * This program is free software; you can redistribute it and/or modify
+ * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation, either version 3 of the License, or
  * (at your option) any later version.
  *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
- * USA
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+/** @file clients/disorder.c
+ * @brief Command-line client
  */
 
 #include "common.h"
@@ -31,6 +32,7 @@
 #include <unistd.h>
 #include <pcre.h>
 #include <ctype.h>
+#include <gcrypt.h>
 #include <langinfo.h>
 
 #include "configuration.h"
@@ -50,6 +52,7 @@
 #include "vector.h"
 #include "version.h"
 #include "dateparse.h"
+#include "trackdb.h"
 #include "inputline.h"
 
 static disorder_client *client;
@@ -64,6 +67,7 @@ static const struct option options[] = {
   { "help-commands", no_argument, 0, 'H' },
   { "user", required_argument, 0, 'u' },
   { "password", required_argument, 0, 'p' },
+  { "wait-for-root", no_argument, 0, 'W' },
   { 0, 0, 0, 0 }
 };
 
@@ -100,8 +104,17 @@ static void cf_version(char attribute((unused)) **argv) {
 static void print_queue_entry(const struct queue_entry *q) {
   if(q->track) xprintf("track %s\n", nullcheck(utf82mb(q->track)));
   if(q->id) xprintf("  id %s\n", nullcheck(utf82mb(q->id)));
-  if(q->submitter) xprintf("  submitted by %s at %s",
-                          nullcheck(utf82mb(q->submitter)), ctime(&q->when));
+  switch(q->origin) {
+  case origin_adopted:
+  case origin_picked:
+  case origin_scheduled:
+    xprintf("  %s by %s at %s",
+            track_origins[q->origin],
+            nullcheck(utf82mb(q->submitter)), ctime(&q->when));
+    break;
+  default:
+    break;
+  }
   if(q->played) xprintf("  played at %s", ctime(&q->played));
   if(q->state == playing_started
      || q->state == playing_paused) xprintf("  %lds so far",  q->sofar);
@@ -149,7 +162,7 @@ static void cf_shutdown(char attribute((unused)) **argv) {
 
 static void cf_reconfigure(char attribute((unused)) **argv) {
   /* Re-check configuration for server */
-  if(config_read(1)) fatal(0, "cannot read configuration");
+  if(config_read(1, NULL)) fatal(0, "cannot read configuration");
   if(disorder_reconfigure(getclient())) exit(EXIT_FAILURE);
 }
 
@@ -588,6 +601,11 @@ static void cf_schedule_unset_global(char **argv) {
     exit(EXIT_FAILURE);
 }
 
+static void cf_adopt(char **argv) {
+  if(disorder_adopt(getclient(), argv[0]))
+    exit(EXIT_FAILURE);
+}
+
 static void cf_playlists(char attribute((unused)) **argv) {
   char **vec;
 
@@ -652,6 +670,8 @@ static const struct command {
 } commands[] = {
   { "adduser",        2, 3, cf_adduser, isarg_rights, "USERNAME PASSWORD [RIGHTS]",
                       "Create a new user" },
+  { "adopt",          1, 1, cf_adopt, 0, "ID",
+                      "Adopt a randomly picked track" },
   { "allfiles",       1, 2, cf_allfiles, isarg_regexp, "DIR [~REGEXP]",
                       "List all files and directories in DIR" },
   { "authorize",      1, 2, cf_authorize, isarg_rights, "USERNAME [RIGHTS]",
@@ -794,8 +814,28 @@ static void help_commands(void) {
   exit(0);
 }
 
+static void wait_for_root(void) {
+  const char *password;
+
+  while(!trackdb_readable()) {
+    info("waiting for trackdb...");
+    sleep(1);
+  }
+  trackdb_init(TRACKDB_NO_RECOVER|TRACKDB_NO_UPGRADE);
+  for(;;) {
+    trackdb_open(TRACKDB_READ_ONLY);
+    password = trackdb_get_password("root");
+    trackdb_close();
+    if(password)
+      break;
+    info("waiting for root user to be created...");
+    sleep(1);
+  }
+  trackdb_deinit(NULL);
+}
+
 int main(int argc, char **argv) {
-  int n, i, j, local = 0;
+  int n, i, j, local = 0, wfr = 0;
   int status = 0;
   struct vector args;
   const char *user = 0, *password = 0;
@@ -806,7 +846,7 @@ int main(int argc, char **argv) {
   pcre_free = xfree;
   if(!setlocale(LC_CTYPE, "")) fatal(errno, "error calling setlocale");
   if(!setlocale(LC_TIME, "")) fatal(errno, "error calling setlocale");
-  while((n = getopt_long(argc, argv, "+hVc:dHlNu:p:", options, 0)) >= 0) {
+  while((n = getopt_long(argc, argv, "+hVc:dHlNu:p:W", options, 0)) >= 0) {
     switch(n) {
     case 'h': help();
     case 'H': help_commands();
@@ -817,10 +857,11 @@ int main(int argc, char **argv) {
     case 'N': config_per_user = 0; break;
     case 'u': user = optarg; break;
     case 'p': password = optarg; break;
+    case 'W': wfr = 1; break;
     default: fatal(0, "invalid option");
     }
   }
-  if(config_read(0)) fatal(0, "cannot read configuration");
+  if(config_read(0, NULL)) fatal(0, "cannot read configuration");
   if(user) {
     config->username = user;
     config->password = 0;
@@ -828,9 +869,16 @@ int main(int argc, char **argv) {
   if(password)
     config->password = password;
   if(local)
-    config->connect.n = 0;
+    config->connect.af = -1;
+  if(wfr)
+    wait_for_root();
   n = optind;
   optind = 1;                          /* for subsequent getopt calls */
+  /* gcrypt initialization */
+  if(!gcry_check_version(NULL))
+    disorder_fatal(0, "gcry_check_version failed");
+  gcry_control(GCRYCTL_INIT_SECMEM, 0);
+  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
   /* accumulate command args */
   while(n < argc) {
     if((i = TABLE_FIND(commands, name, argv[n])) < 0)