]> mj.ucw.cz Git - misc.git/commitdiff
Ursary: Moved to a separate repo
authorMartin Mares <mj@ucw.cz>
Sun, 9 Nov 2014 23:39:09 +0000 (00:39 +0100)
committerMartin Mares <mj@ucw.cz>
Sun, 9 Nov 2014 23:39:09 +0000 (00:39 +0100)
ursaryd/DESC [deleted file]
ursaryd/Makefile [deleted file]
ursaryd/jt.c [deleted file]
ursaryd/mpd.c [deleted file]
ursaryd/nocturn.c [deleted file]
ursaryd/pulse-ucw.c [deleted file]
ursaryd/pulse.c [deleted file]
ursaryd/ursaryd.c [deleted file]
ursaryd/ursaryd.h [deleted file]

diff --git a/ursaryd/DESC b/ursaryd/DESC
deleted file mode 100644 (file)
index ca25e81..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-Bus 006 Device 003: ID 1235:000a Novation EMS 
-Device Descriptor:
-  bLength                18
-  bDescriptorType         1
-  bcdUSB               1.00
-  bDeviceClass          255 Vendor Specific Class
-  bDeviceSubClass         0 
-  bDeviceProtocol       255 
-  bMaxPacketSize0         8
-  idVendor           0x1235 Novation EMS
-  idProduct          0x000a 
-  bcdDevice            0.09
-  iManufacturer           1 Novation DMS Ltd
-  iProduct                2 Nocturn
-  iSerial                 0 
-  bNumConfigurations      2
-  Configuration Descriptor:
-    bLength                 9
-    bDescriptorType         2
-    wTotalLength           32
-    bNumInterfaces          1
-    bConfigurationValue     1
-    iConfiguration          3 High brightness mode
-    bmAttributes         0x80
-      (Bus Powered)
-    MaxPower              220mA
-    Interface Descriptor:
-      bLength                 9
-      bDescriptorType         4
-      bInterfaceNumber        0
-      bAlternateSetting       0
-      bNumEndpoints           2
-      bInterfaceClass       255 Vendor Specific Class
-      bInterfaceSubClass      0 
-      bInterfaceProtocol      0 
-      iInterface              0 
-      Endpoint Descriptor:
-        bLength                 7
-        bDescriptorType         5
-        bEndpointAddress     0x81  EP 1 IN
-        bmAttributes            3
-          Transfer Type            Interrupt
-          Synch Type               None
-          Usage Type               Data
-        wMaxPacketSize     0x0008  1x 8 bytes
-        bInterval              10
-      Endpoint Descriptor:
-        bLength                 7
-        bDescriptorType         5
-        bEndpointAddress     0x02  EP 2 OUT
-        bmAttributes            3
-          Transfer Type            Interrupt
-          Synch Type               None
-          Usage Type               Data
-        wMaxPacketSize     0x0008  1x 8 bytes
-        bInterval              10
-  Configuration Descriptor:
-    bLength                 9
-    bDescriptorType         2
-    wTotalLength           32
-    bNumInterfaces          1
-    bConfigurationValue     2
-    iConfiguration          4 Power saving mode
-    bmAttributes         0x80
-      (Bus Powered)
-    MaxPower              110mA
-    Interface Descriptor:
-      bLength                 9
-      bDescriptorType         4
-      bInterfaceNumber        0
-      bAlternateSetting       0
-      bNumEndpoints           2
-      bInterfaceClass       255 Vendor Specific Class
-      bInterfaceSubClass      0 
-      bInterfaceProtocol      0 
-      iInterface              0 
-      Endpoint Descriptor:
-        bLength                 7
-        bDescriptorType         5
-        bEndpointAddress     0x81  EP 1 IN
-        bmAttributes            3
-          Transfer Type            Interrupt
-          Synch Type               None
-          Usage Type               Data
-        wMaxPacketSize     0x0008  1x 8 bytes
-        bInterval              10
-      Endpoint Descriptor:
-        bLength                 7
-        bDescriptorType         5
-        bEndpointAddress     0x02  EP 2 OUT
-        bmAttributes            3
-          Transfer Type            Interrupt
-          Synch Type               None
-          Usage Type               Data
-        wMaxPacketSize     0x0008  1x 8 bytes
-        bInterval              10
-Device Status:     0x0000
-  (Bus Powered)
diff --git a/ursaryd/Makefile b/ursaryd/Makefile
deleted file mode 100644 (file)
index 5d8d44c..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-LIBUSB_CFLAGS := $(shell pkg-config --cflags libusb-1.0)
-LIBUSB_LIBS := $(shell pkg-config --libs libusb-1.0)
-
-LIBPULSE_CFLAGS := $(shell pkg-config --cflags libpulse)
-LIBPULSE_LIBS := $(shell pkg-config --libs libpulse)
-
-LIBUCW_PKG := /home/mj/src/libucw/run/lib/pkgconfig
-LIBUCW_CFLAGS := $(shell PKG_CONFIG_PATH=$(LIBUCW_PKG) pkg-config --cflags libucw)
-LIBUCW_LIBS := $(shell PKG_CONFIG_PATH=$(LIBUCW_PKG) pkg-config --libs libucw)
-
-CFLAGS=-O2 -Wall -W -Wno-parentheses -Wstrict-prototypes -Wmissing-prototypes -Wundef -Wredundant-decls -std=gnu99 $(LIBUCW_CFLAGS) $(LIBUSB_CFLAGS) $(LIBPULSE_CFLAGS) -g2
-LDLIBS=$(LIBUCW_LIBS) $(LIBUSB_LIBS) $(LIBPULSE_LIBS)
-
-all: ursaryd
-
-ursaryd: ursaryd.o mpd.o nocturn.o pulse.o pulse-ucw.o
-
-ursaryd.o: ursaryd.c ursaryd.h
-mpd.o: mpd.c ursaryd.h
-nocturn.o: nocturn.c ursaryd.h
-pulse.o: pulse.c ursaryd.h
-pulse-ucw.o: pulse-ucw.c ursaryd.h
-
-clean:
-       rm -f `find . -name "*~" -or -name "*.[oa]" -or -name "\#*\#" -or -name TAGS -or -name core -or -name .depend -or -name .#*`
-       rm -f ursaryd
diff --git a/ursaryd/jt.c b/ursaryd/jt.c
deleted file mode 100644 (file)
index 3fa5558..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <jack/jack.h>
-
-typedef jack_default_audio_sample_t sample_t;
-
-static jack_client_t *jc;
-static jack_port_t *inport[2], *outport[4];
-
-static int process_callback(jack_nframes_t nframes, void *arg __attribute__((unused)))
-{
-       for (int ch=0; ch<2; ch++) {
-               sample_t *in = jack_port_get_buffer(inport[ch], nframes);
-               sample_t *out = jack_port_get_buffer(outport[ch], nframes);
-               sample_t *out2 = jack_port_get_buffer(outport[2+ch], nframes);
-               for (jack_nframes_t i=0; i<nframes; i++) {
-                       out[i] = in[i];
-                       out2[i] = in[i];
-               }
-       }
-       return 0;
-}
-
-static void port_callback(jack_port_id_t id, int reg, void *arg __attribute__((unused)))
-{
-       jack_port_t *p = jack_port_by_id(jc, id);
-       if (!p) {
-               puts("port_callback: lookup failed");
-               return;
-       }
-       const char *name = jack_port_name(p);
-       printf("%s port %s\n", (reg ? "Registered" : "Unregistered"), name);
-
-       const char *ss = strstr(name, ":from_slave_");
-       if (reg && ss) {
-               char *to = (ss[12] == '1' ? "brum:in1" : "brum:in2");
-               printf("\t... connecting to %s\n", to);
-               if (jack_connect(jc, name, to))
-                       puts("jack_connect failed");
-       }
-}
-
-int main(void)
-{
-       jc = jack_client_open("brum", JackNoStartServer, NULL);
-       if (!jc) {
-               puts("jack_client_open failed");
-               return 1;
-       }
-
-       for (int i=0; i<2; i++) {
-               char name[16];
-               sprintf(name, "in%d", i+1);
-               inport[i] = jack_port_register(jc, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0);
-               if (!inport[i]) {
-                       puts("jack_port_register failed");
-                       return 1;
-               }
-       }
-
-       for (int i=0; i<4; i++) {
-               char name[16];
-               sprintf(name, "out%d", i+1);
-               outport[i] = jack_port_register(jc, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
-               if (!outport[i]) {
-                       puts("jack_port_register failed");
-                       return 1;
-               }
-       }
-
-       jack_set_process_callback(jc, process_callback, NULL);
-       jack_set_port_registration_callback(jc, port_callback, NULL);
-
-       if (jack_activate(jc)) {
-               puts("jack_activate failed");
-               return 1;
-       }
-
-       puts("Connecting ports...");
-       for (int i=1; i<=4; i++) {
-               char a[32], b[32];
-               sprintf(a, "brum:out%d", i);
-               sprintf(b, "system:playback_%d", i);
-               if (jack_connect(jc, a, b))
-                       printf("Failed to connect %s -> %s\n", a, b);
-       }
-
-       puts("Running...");
-       char xxx[16];
-       read(0, xxx, sizeof(xxx));
-
-       puts("exiting");
-       jack_client_close(jc);
-       return 0;
-}
diff --git a/ursaryd/mpd.c b/ursaryd/mpd.c
deleted file mode 100644 (file)
index f0da2a3..0000000
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- *     Interface to Music Player Daemon
- *
- *     (c) 2014 Martin Mares <mj@ucw.cz>
- */
-
-#define LOCAL_DEBUG
-
-#include <ucw/lib.h>
-#include <ucw/clists.h>
-#include <ucw/mainloop.h>
-#include <ucw/mempool.h>
-#include <ucw/simple-lists.h>
-#include <ucw/stkstring.h>
-#include <ucw/string.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include "ursaryd.h"
-
-static struct main_timer mpd_connect_timer;
-static struct main_file mpd_connect_file;
-static struct main_rec_io mpd_rio;
-static int mpd_sk = -1;
-
-enum mpd_state mpd_state;
-#define MPD_STATE(s) do { mpd_state = s; DBG("MPD: " #s); } while (0)
-
-struct mpd_cmd {                       // malloc'ed
-  cnode n;
-  char *cmd;                           // malloc'ed
-  void (*done)(struct mpd_cmd *c);
-  char *status;
-  int err;
-  int idle;                            // 1=this is an idle command, 2=aborted idle command
-  clist output;                                // list of simp2_node's allocated from mpd_reply_pool
-};
-
-static clist mpd_cmd_queue;
-static struct mpd_cmd *mpd_current_command;            // ... at the head of the queue
-static struct mempool *mpd_reply_pool;
-
-static void mpd_send_cmd(void);
-static void mpd_cmd(void (*done)(struct mpd_cmd *c), const char *cmd, ...);
-
-static struct mpd_cmd *mpd_new_cmd(void)
-{
-  struct mpd_cmd *c = xmalloc_zero(sizeof(*c));
-  clist_add_tail(&mpd_cmd_queue, &c->n);
-  clist_init(&c->output);
-  return c;
-}
-
-static void mpd_free_cmd(struct mpd_cmd *c)
-{
-  xfree(c->cmd);
-  xfree(c);
-}
-
-static void mpd_error(const char *text, ...)
-{
-  va_list args;
-  va_start(args, text);
-  const char *x = stk_vprintf(text, args);
-  msg(L_ERROR, "MPD: %s", x);
-  va_end(args);
-
-  DBG("MPD: Flushing commands");
-  mpd_current_command = NULL;
-  struct mpd_cmd *c;
-  while (c = (struct mpd_cmd *) clist_remove_head(&mpd_cmd_queue))
-    mpd_free_cmd(c);
-
-  DBG("MPD: Tearing down server connection");
-  rec_io_del(&mpd_rio);
-  file_del(&mpd_connect_file);
-  if (mpd_sk >= 0)
-    {
-      close(mpd_sk);
-      mpd_sk = -1;
-    }
-
-  DBG("MPD: Scheduling reconnect");
-  timer_add_rel(&mpd_connect_timer, 5000);
-  MPD_STATE(MPD_OFFLINE);
-  schedule_update();
-}
-
-static void mpd_cmd_done(struct mpd_cmd *c)
-{
-  DBG("MPD: Command finished (err=%d)", c->err);
-  rec_io_set_timeout(&mpd_rio, 0);
-  if (c->done)
-    c->done(c);
-  clist_remove(&c->n);
-  mpd_free_cmd(c);
-
-  mpd_current_command = NULL;
-  mpd_send_cmd();
-}
-
-static const char *mpd_find_output(struct mpd_cmd *c, const char *key, const char *deflt)
-{
-  CLIST_FOR_EACH(struct simp2_node *, n, c->output)
-    if (!strcmp(n->s1, key))
-      return n->s2;
-  return deflt;
-}
-
-static char *mpd_player_state;
-
-static void mpd_got_status(struct mpd_cmd *c)
-{
-  const char *state = mpd_find_output(c, "state", "");
-  DBG("MPD: Player state <%s>", state);
-  SET_STRING(mpd_player_state, state);
-  schedule_update();
-}
-
-const char *mpd_get_player_state(void)
-{
-  if (mpd_state != MPD_ONLINE)
-    return "down";
-  else if (mpd_player_state)
-    return mpd_player_state;
-  else
-    return "unknown";
-}
-
-static void mpd_got_idle(struct mpd_cmd *c)
-{
-  const char *chg = mpd_find_output(c, "changed", "");
-  if (!strcmp(chg, "player"))
-    mpd_cmd(mpd_got_status, "status");
-}
-
-static bool mpd_got_line(char *line)
-{
-  if (mpd_state == MPD_WAIT_GREETING)
-    {
-      if (!str_has_prefix(line, "OK "))
-       mpd_error("Invalid welcome line");
-      MPD_STATE(MPD_ONLINE);
-      mpd_cmd(mpd_got_status, "status");
-      return 1;
-    }
-
-  ASSERT(mpd_state == MPD_ONLINE);
-
-  struct mpd_cmd *c = mpd_current_command;
-  if (!c)
-    {
-      mpd_error("Reply for no command");
-      return 0;
-    }
-
-  if (!strcmp(line, "OK"))
-    {
-      c->status = line;
-      c->err = 0;
-      mpd_cmd_done(c);
-    }
-  else if (str_has_prefix(line, "ACK "))
-    {
-      c->status = line;
-      if (line[4] != '[')
-       {
-         mpd_error("Reply syntax error: <%s>", line);
-         return 0;
-       }
-      c->err = atoi(line+5);
-      mpd_cmd_done(c);
-    }
-  else
-    {
-      char *sep = strchr(line, ':');
-      if (!sep || sep[1] != ' ')
-       {
-         mpd_error("Reply syntax error: <%s>", line);
-         return 0;
-       }
-      *sep++ = 0;
-      *sep++ = 0;
-      simp2_node *sn = simp2_append(mpd_reply_pool, &c->output);
-      sn->s1 = mp_strdup(mpd_reply_pool, line);
-      sn->s2 = mp_strdup(mpd_reply_pool, sep);
-    }
-
-  return 1;
-}
-
-static uint mpd_read_handler(struct main_rec_io *rio)
-{
-  uint len = rec_io_parse_line(rio);
-  if (!len)
-    return 0;
-
-  char line[len];
-  memcpy(line, rio->read_rec_start, len-1);
-  line[len-1] = 0;
-
-  DBG("Received <%s>", line);
-  if (mpd_got_line(line))
-    return len;
-  else
-    return ~0U;
-}
-
-static int mpd_notify_handler(struct main_rec_io *rio UNUSED, int status)
-{
-  switch (status)
-    {
-    case RIO_EVENT_EOF:
-      mpd_error("Connection closed by server");
-      return HOOK_IDLE;
-    default:
-      if (status < 0)
-       {
-         mpd_error("Error on server connection (status=%d errno=%d)", status, errno);
-         return HOOK_IDLE;
-       }
-      return HOOK_RETRY;
-    }
-}
-
-static void mpd_send_cmd(void)
-{
-  struct mpd_cmd *c;
-
-  if (c = mpd_current_command)
-    {
-      if (c->idle == 1)
-       {
-         DBG("MPD: Sending noidle");
-         rec_io_write(&mpd_rio, "noidle\n", 7);
-         c->idle = 2;
-       }
-      return;
-    }
-
-  c = (struct mpd_cmd *) clist_head(&mpd_cmd_queue);
-  if (!c)
-    {
-      c = mpd_new_cmd();
-      c->cmd = malloc(6);
-      strcpy(c->cmd, "idle\n");
-      c->idle = 1;
-      c->done = mpd_got_idle;
-    }
-  mpd_current_command = c;
-
-  DBG("MPD: Sending command <%s>", c->cmd);
-  rec_io_write(&mpd_rio, c->cmd, strlen(c->cmd));
-  if (!c->idle)
-    rec_io_set_timeout(&mpd_rio, 5000);
-}
-
-static void mpd_cmd(void (*done)(struct mpd_cmd *c), const char *cmd, ...)
-{
-  struct mpd_cmd *c = mpd_new_cmd();
-  c->done = done;
-
-  va_list args, args2;
-  va_start(args, cmd);
-  va_copy(args2, args);
-  int len = vsnprintf(NULL, 0, cmd, args);
-  c->cmd = xmalloc(len + 2);
-  vsnprintf(c->cmd, len + 1, cmd, args2);
-  c->cmd[len] = '\n';
-  c->cmd[len+1] = 0;
-  va_end(args);
-  va_end(args2);
-
-  mpd_send_cmd();
-}
-
-static int mpd_connected(struct main_file *f)
-{
-  if (f)
-    {
-      // Called from the hook
-      DBG("MPD: Connection hook");
-      file_del(f);
-      timer_del(&mpd_connect_timer);
-      int err;
-      socklen_t len = sizeof(err);
-      if (getsockopt(mpd_sk, SOL_SOCKET, SO_ERROR, &err, &len) < 0)
-       ASSERT(0);
-      if (err)
-       {
-         mpd_error("Connection refused: %s", strerror(err));
-         return HOOK_IDLE;
-       }
-    }
-
-  MPD_STATE(MPD_WAIT_GREETING);
-  mpd_rio.read_handler = mpd_read_handler;
-  mpd_rio.notify_handler = mpd_notify_handler;
-  mpd_rio.read_rec_max = 16384;
-  rec_io_add(&mpd_rio, mpd_sk);
-  rec_io_start_read(&mpd_rio);
-
-  return HOOK_IDLE;
-}
-
-void mpd_play(void)
-{
-  return mpd_cmd(NULL, "play");
-}
-
-void mpd_stop(void)
-{
-  return mpd_cmd(NULL, "stop");
-}
-
-void mpd_pause(int arg)
-{
-  return mpd_cmd(NULL, "pause %d", arg);
-}
-
-static void mpd_connect(struct main_timer *t)
-{
-  timer_del(t);
-
-  if (mpd_state == MPD_CONNECTING)
-    {
-      mpd_error("Attempt to connect timed out");
-      return;
-    }
-
-  DBG("MPD: Trying to connect");
-
-  mpd_sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-  if (mpd_sk < 0)
-    die("Cannot create socket: %m");
-
-  fcntl(mpd_sk, F_SETFL, fcntl(mpd_sk, F_GETFL) | O_NONBLOCK);
-
-  bzero(&mpd_rio, sizeof(mpd_rio));
-  bzero(&mpd_connect_file, sizeof(mpd_connect_file));
-  mpd_connect_file.fd = mpd_sk;
-  mpd_connect_file.write_handler = mpd_connected;
-  MPD_STATE(MPD_CONNECTING);
-
-  struct sockaddr_in sin;
-  sin.sin_family = AF_INET;
-  sin.sin_port = htons(6600);
-  sin.sin_addr.s_addr = htonl(0x7f000001);
-  if (connect(mpd_sk, (struct sockaddr *) &sin, sizeof(sin)) < 0)
-    {
-      if (errno == EINPROGRESS)
-       {
-         file_add(&mpd_connect_file);
-         timer_add_rel(&mpd_connect_timer, 5000);
-       }
-      else
-       mpd_error("Unable to connect: %m");
-    }
-  else
-    mpd_connected(NULL);
-}
-
-void mpd_init(void)
-{
-  clist_init(&mpd_cmd_queue);
-  mpd_reply_pool = mp_new(4096);
-
-  mpd_connect_timer.handler = mpd_connect;
-  timer_add_rel(&mpd_connect_timer, 100);
-  mpd_state = MPD_OFFLINE;
-}
diff --git a/ursaryd/nocturn.c b/ursaryd/nocturn.c
deleted file mode 100644 (file)
index ba5edf2..0000000
+++ /dev/null
@@ -1,507 +0,0 @@
-/*
- *     Interface to Novation Nocturn
- *
- *     (c) 2014 Martin Mares <mj@ucw.cz>
- *
- *     Protocol reverse-engineered by De Wet van Niekerk <dewert@gmail.com>,
- *     see https://github.com/dewert/nocturn-linux-midi for inspiration.
- */
-
-#undef LOCAL_DEBUG
-
-#include <ucw/lib.h>
-#include <ucw/bitops.h>
-#include <ucw/clists.h>
-#include <ucw/gary.h>
-#include <ucw/mainloop.h>
-#include <ucw/stkstring.h>
-#include <ucw/string.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <sys/poll.h>
-
-#include <libusb.h>
-
-#include "ursaryd.h"
-
-static libusb_context *usb_ctx;
-static libusb_device_handle *usb_dev;
-static bool usb_iface_claimed;
-
-static void noct_error(int usb_err, char *text);
-
-static struct main_file **usb_fds;
-
-static int usb_fd_ready(struct main_file *f UNUSED)
-{
-  DBG("USB: Handling events (ready on fd %d)", f->fd);
-  struct timeval tv = { 0, 0 };
-  int comp = 0;
-  int err = libusb_handle_events_timeout_completed(usb_ctx, &tv, &comp);
-  if (err < 0)
-    msg(L_ERROR, "libusb_handle_events: error %d", err);
-  return HOOK_IDLE;
-}
-
-static void usb_added_fd(int fd, short events, void *user_data UNUSED)
-{
-  if (fd >= (int) GARY_SIZE(usb_fds))
-    GARY_RESIZE(usb_fds, fd + 1);
-
-  struct main_file *f = usb_fds[fd];
-  if (!f)
-    {
-      f = xmalloc_zero(sizeof(*f));
-      usb_fds[fd] = f;
-    }
-  else if (file_is_active(f))
-    {
-      DBG("USB: Releasing fd %d", fd);
-      file_del(f);
-    }
-
-  DBG("USB: Adding fd %d with event mask %u", fd, events);
-  f->fd = fd;
-  f->read_handler = (events & POLLIN) ? usb_fd_ready : NULL;
-  f->write_handler = (events & POLLOUT) ? usb_fd_ready : NULL;
-  file_add(f);
-}
-
-static void usb_removed_fd(int fd, void *user_data UNUSED)
-{
-  DBG("USB: Releasing fd %d", fd);
-  ASSERT(fd < (int) GARY_SIZE(usb_fds));
-  struct main_file *f = usb_fds[fd];
-  ASSERT(f);
-  ASSERT(file_is_active(f));
-  file_del(f);
-}
-
-static const char noct_magic[4][9] = {
-  { 3, 0xb0, 0x00, 0x00 },
-  { 8, 0x28, 0x00, 0x2b, 0x4a, 0x2c, 0x00, 0x2e, 0x35 },
-  { 6, 0x2a, 0x02, 0x2c, 0x72, 0x2e, 0x30 },
-  { 2, 0x7f, 0x00 },
-};
-
-static struct libusb_transfer *noct_read_xfer;
-static bool noct_read_pending;
-char noct_rotary_touched[10];
-char noct_button_pressed[16];
-
-static void noct_read_done(struct libusb_transfer *xfer)
-{
-  byte *pkt = xfer->buffer;
-  int len = xfer->actual_length;
-  DBG("USB: Read done: status %d, length %d", xfer->status, len);
-  noct_read_pending = 0;
-
-  if (xfer->status != LIBUSB_TRANSFER_COMPLETED)
-    return noct_error(0, stk_printf("USB read failed with status %d", xfer->status));
-
-#ifdef LOCAL_DEBUG
-  char buf[256];
-  mem_to_hex(buf, pkt, len, ' ');
-  DBG("USB: Read <%s>", buf);
-#endif
-
-  int i = 0;
-  while (i < len)
-    {
-      if (i + 3 > len)
-       {
-         msg(L_ERROR, "Unknown USB packet: length %d not divisible by 3", len);
-         break;
-       }
-      if (pkt[i] != 0xb0)
-       {
-         msg(L_ERROR, "Unknown USB packet: expected 0xb0 at position %d", i);
-         break;
-       }
-      int cmd = pkt[i+1];
-      int arg = pkt[i+2];
-      i += 3;
-      switch (cmd)
-       {
-       case 0x30:
-         // Unknown packet sent during init
-         continue;
-       case 0x40 ... 0x47:
-         if (arg < 0x80)
-           {
-             int r = cmd - 0x40;
-             int delta = (arg < 0x40 ? arg : arg - 0x80);
-             DBG("Noct: Rotary %d = %d", r, delta);
-             notify_rotary(r, delta);
-             continue;
-           }
-         break;
-       case 0x48:
-         if (arg < 0x80)
-           {
-             DBG("Noct: Slider value = %d", arg);
-             notify_rotary(9, arg);
-             continue;
-           }
-         break;
-       case 0x49:
-         // Unknown packet, maybe least significant bit of slider
-         continue;
-       case 0x4a:
-         if (arg < 0x80)
-           {
-             int delta = (arg < 0x40 ? arg : arg - 0x80);
-             DBG("Noct: Center = %d", delta);
-             notify_rotary(8, delta);
-             continue;
-           }
-         break;
-       case 0x52:
-         if (arg == 0x00 || arg == 0x7f)
-           {
-             int state = !!arg;
-             DBG("Noct: Center touch = %d", state);
-             noct_rotary_touched[8] = state;
-             notify_touch(8, state);
-             continue;
-           }
-         break;
-       case 0x53:
-         if (arg == 0x00 || arg == 0x7f)
-           {
-             int state = !!arg;
-             DBG("Noct: Slider touch = %d", state);
-             noct_rotary_touched[9] = state;
-             notify_touch(9, state);
-             continue;
-           }
-         break;
-       case 0x60 ... 0x67:
-         if (arg == 0x00 || arg == 0x7f)
-           {
-             int r = cmd - 0x60;
-             int state = !!arg;
-             DBG("Noct: Rotary %d touch = %d", r, state);
-             noct_rotary_touched[r] = state;
-             notify_touch(r, state);
-             continue;
-           }
-         break;
-       case 0x70 ... 0x7f:
-         if (arg == 0x00 || arg == 0x7f)
-           {
-             int b = cmd - 0x70;
-             int state = !!arg;
-             DBG("Noct: Button %d = %d", b, state);
-             noct_button_pressed[b] = state;
-             notify_button(b, state);
-             continue;
-           }
-         break;
-       }
-      msg(L_ERROR, "Unknown USB packet: unrecognized cmd=%02x arg=%02x", cmd, arg);
-    }
-
-  int err;
-  if ((err = libusb_submit_transfer(xfer)) < 0)
-    noct_error(err, "Cannot submit transfer");
-  else
-    noct_read_pending = 1;
-}
-
-static void noct_read_init(void)
-{
-  DBG("Noct: Read init");
-
-  noct_read_xfer = libusb_alloc_transfer(0);
-  libusb_fill_interrupt_transfer(noct_read_xfer, usb_dev, 0x81, xmalloc(8), 8, noct_read_done, NULL, 0);
-
-  int err;
-  if ((err = libusb_submit_transfer(noct_read_xfer)) < 0)
-    noct_error(err, "Cannot submit transfer");
-  else
-    noct_read_pending = 1;
-}
-
-static byte noct_button_light[16];
-static byte noct_ring_mode[8];         // RING_MODE_xxx
-static byte noct_ring_val[9];
-
-static uint noct_dirty_button;
-static uint noct_dirty_ring_mode;
-static uint noct_dirty_ring_val;
-
-static struct libusb_transfer *noct_write_xfer;
-static bool noct_write_pending;
-static void noct_sched_write(void);
-
-static void noct_write_done(struct libusb_transfer *xfer)
-{
-  int len = xfer->actual_length;
-  DBG("USB: Write done: status %d, length %d", xfer->status, len);
-
-  if (xfer->status != LIBUSB_TRANSFER_COMPLETED)
-    return noct_error(0, stk_printf("USB write failed with status %d", xfer->status));
-  if (len < xfer->length)
-    msg(L_ERROR, "USB partial write: %d out of %d", len, xfer->length);
-
-  noct_write_pending = 0;
-  noct_sched_write();
-}
-
-static void noct_do_write(uint cmd, uint arg)
-{
-  DBG("USB: Submitting write %02x %02x", cmd, arg);
-  ASSERT(!noct_write_pending);
-  noct_write_pending = 1;
-
-  struct libusb_transfer *xfer = noct_write_xfer;
-  byte *pkt = xfer->buffer;
-  pkt[0] = cmd;
-  pkt[1] = arg;
-  xfer->length = 2;
-
-  int err;
-  if ((err = libusb_submit_transfer(xfer)) < 0)
-    noct_error(err, "Cannot submit transfer");
-}
-
-static void noct_sched_write(void)
-{
-  if (noct_write_pending)
-    return;
-
-  if (noct_dirty_button)
-    {
-      int i = bit_ffs(noct_dirty_button);
-      noct_dirty_button ^= 1U << i;
-      noct_do_write(0x70 + i, noct_button_light[i]);
-    }
-  else if (noct_dirty_ring_mode)
-    {
-      int i = bit_ffs(noct_dirty_ring_mode);
-      noct_dirty_ring_mode ^= 1U << i;
-      noct_do_write(0x48 + i, noct_ring_mode[i] << 4);
-    }
-  else if (noct_dirty_ring_val)
-    {
-      int i = bit_ffs(noct_dirty_ring_val);
-      noct_dirty_ring_val ^= 1U << i;
-      if (i == 8)
-       noct_do_write(0x50, noct_ring_val[i]);
-      else
-       noct_do_write(0x40 + i, noct_ring_val[i]);
-    }
-}
-
-void noct_set_ring(int ring, int mode, int val)
-{
-  ASSERT(ring >= 0 && ring <= 8);
-  ASSERT(val >= 0 && val <= 0x7f);
-  ASSERT(mode >= 0 && mode <= 5);
-  ASSERT(ring < 8 || !mode);
-  if (noct_ring_mode[ring] != mode)
-    {
-      noct_ring_mode[ring] = mode;
-      noct_dirty_ring_mode |= 1U << ring;
-      noct_dirty_ring_val |= 1U << ring;       // HW needs to re-send the value
-    }
-  if (noct_ring_val[ring] != val)
-    {
-      noct_ring_val[ring] = val;
-      noct_dirty_ring_val |= 1U << ring;
-    }
-  noct_sched_write();
-}
-
-void noct_set_button(int button, int val)
-{
-  ASSERT(button >= 0 && button < 16);
-  ASSERT(val == 0 || val == 1);
-  if (noct_button_light[button] != val)
-    {
-      noct_button_light[button] = val;
-      noct_dirty_button |= 1U << button;
-      noct_sched_write();
-    }
-}
-
-static void noct_write_init(void)
-{
-  DBG("Noct: Write init");
-
-  noct_write_xfer = libusb_alloc_transfer(0);
-  libusb_fill_interrupt_transfer(noct_write_xfer, usb_dev, 0x02, xmalloc(8), 0, noct_write_done, NULL, 1000);
-
-  bzero(noct_button_pressed, sizeof(noct_button_pressed));
-  bzero(noct_rotary_touched, sizeof(noct_rotary_touched));
-  noct_dirty_button = 0xffff;
-  noct_dirty_ring_mode = 0xff;
-  noct_dirty_ring_val = 0x1ff;
-  noct_sched_write();
-}
-
-static struct main_timer noct_connect_timer;
-static struct main_hook noct_error_hook;
-
-static void noct_connect(struct main_timer *t)
-{
-  timer_del(t);
-  msg(L_DEBUG, "Looking for Nocturn");
-  int err;
-
-  libusb_device **dev_list;
-  libusb_device *found_dev = NULL;
-  ssize_t len = libusb_get_device_list(usb_ctx, &dev_list);
-  for (ssize_t i=0; i < len; i++)
-    {
-      libusb_device *dev = dev_list[i];
-      struct libusb_device_descriptor desc;
-      if (libusb_get_device_descriptor(dev, &desc) >= 0 &&
-         desc.idVendor == 0x1235 &&
-         desc.idProduct == 0x000a)
-       {
-         msg(L_INFO, "Nocturn found at bus %d, addr %d", libusb_get_bus_number(dev), libusb_get_device_address(dev));
-         if (found_dev)
-           {
-             msg(L_ERROR, "Multiple Nocturn devices found. Using the first one.");
-             break;
-           }
-         found_dev = libusb_ref_device(dev);
-       }
-    }
-  libusb_free_device_list(dev_list, 1);
-
-  if (!found_dev)
-    {
-      msg(L_INFO, "No Nocturn device found");
-      timer_add_rel(t, 5000);
-      return;
-    }
-
-  DBG("Initializing Nocturn");
-
-  if ((err = libusb_open(found_dev, &usb_dev)) < 0)
-    return noct_error(err, "libusb_open failed");
-
-  // There exist configurations 1 (high brightness) and 2 (power-save)
-  if ((err = libusb_set_configuration(usb_dev, 2)) < 0)
-    return noct_error(err, "libusb_set_configuration failed");
-
-  if ((err = libusb_claim_interface(usb_dev, 0)) < 0)
-    return noct_error(err, "libusb_claim_interface failed");
-  usb_iface_claimed = 1;
-
-  for (int i=0; i<4; i++)
-    {
-      int done;
-      if ((err = libusb_interrupt_transfer(usb_dev, 0x02, (byte *) noct_magic[i] + 1, noct_magic[i][0], &done, 5000)) < 0)
-       return noct_error(err, "Cannot send init packets");
-      if (done != noct_magic[i][0])
-       return noct_error(err, stk_printf("Partial send of init packet (%d < %d)", done, noct_magic[i][0]));
-    }
-
-  noct_read_init();
-  noct_write_init();
-  schedule_update();
-}
-
-static int noct_error_handler(struct main_hook *h)
-{
-  DBG("Noct: Entered error handling hook");
-  hook_del(h);
-
-  if (usb_dev)
-    {
-      if (noct_read_xfer)
-       {
-         if (noct_read_pending)
-           {
-             DBG("Noct: Cancelling pending read");
-             libusb_cancel_transfer(noct_read_xfer);
-             noct_read_pending = 0;
-           }
-         DBG("Noct: Tearing down read xfer");
-         xfree(noct_read_xfer->buffer);
-         libusb_free_transfer(noct_read_xfer);
-         noct_read_xfer = NULL;
-       }
-      if (noct_write_xfer)
-       {
-         if (noct_write_pending)
-           {
-             DBG("Noct: Cancelling pending write");
-             libusb_cancel_transfer(noct_write_xfer);
-             noct_write_pending = 0;
-           }
-         DBG("Noct: Tearing down write xfer");
-         xfree(noct_write_xfer->buffer);
-         libusb_free_transfer(noct_write_xfer);
-         noct_write_xfer = NULL;
-       }
-      if (usb_iface_claimed)
-       {
-         DBG("Noct: Unclaiming interface");
-         libusb_release_interface(usb_dev, 0);
-         usb_iface_claimed = 0;
-       }
-      DBG("Noct: Resetting device");
-      libusb_reset_device(usb_dev);
-      libusb_close(usb_dev);
-      usb_dev = NULL;
-    }
-
-  DBG("Noct: Scheduling rescan after error");
-  timer_add_rel(&noct_connect_timer, 3000);
-
-  return HOOK_IDLE;
-}
-
-static void noct_error(int usb_err, char *text)
-{
-  if (usb_err)
-    msg(L_ERROR, "Nocturn: %s: error %d (%s)", text, usb_err, libusb_error_name(usb_err));
-  else
-    msg(L_ERROR, "Nocturn: %s", text);
-
-  DBG("Noct: Scheduling error handling hook");
-  hook_add(&noct_error_hook);
-}
-
-bool noct_is_ready(void)
-{
-  return !!usb_dev;
-}
-
-void noct_init(void)
-{
-  int err;
-
-  // Initialize libusb
-  if ((err = libusb_init(&usb_ctx)) < 0)
-    die("libusb_init failed: error %d", err);
-  libusb_set_debug(usb_ctx, 3);
-
-  // Connect libusb to UCW mainloop
-
-  if (!libusb_pollfds_handle_timeouts(usb_ctx))
-    die("Unsupported version of libusb, please fix me");
-
-  GARY_INIT_ZERO(usb_fds, 0);
-  libusb_set_pollfd_notifiers(usb_ctx, usb_added_fd, usb_removed_fd, NULL);
-
-  const struct libusb_pollfd **fds = libusb_get_pollfds(usb_ctx);
-  ASSERT(fds);
-  for (int i=0; fds[i]; i++)
-    usb_added_fd(fds[i]->fd, fds[i]->events, NULL);
-  free(fds);
-
-  // Prepare error handling hook
-  noct_error_hook.handler = noct_error_handler;
-
-  // Schedule search for the Nocturn
-  noct_connect_timer.handler = noct_connect;
-  timer_add_rel(&noct_connect_timer, 100);
-}
diff --git a/ursaryd/pulse-ucw.c b/ursaryd/pulse-ucw.c
deleted file mode 100644 (file)
index 4ef032c..0000000
+++ /dev/null
@@ -1,356 +0,0 @@
-/*
- *     Glue between PulseAudio and LibUCW Mainloop
- *
- *     (c) 2014 Martin Mares <mj@ucw.cz>
- */
-
-#undef LOCAL_DEBUG
-
-#include <ucw/lib.h>
-#include <ucw/clists.h>
-#include <ucw/mainloop.h>
-
-#include <sys/poll.h>
-#include <sys/time.h>
-
-#include "ursaryd.h"
-
-struct pmain_io {
-  cnode n;
-  struct main_file f;
-  clist io_events;
-};
-
-static clist pmain_io_list;
-
-struct pa_io_event {
-  cnode n;
-  cnode gc_n;
-  struct pmain_io *io;
-  pa_io_event_flags_t events;
-  pa_io_event_cb_t callback;
-  pa_io_event_destroy_cb_t destroy_callback;
-  void *userdata;
-};
-
-static clist pmain_io_gc_list;
-
-static pa_io_event *pmain_io_new(pa_mainloop_api *api, int fd, pa_io_event_flags_t events, pa_io_event_cb_t cb, void *userdata);
-static void pmain_io_enable(pa_io_event *e, pa_io_event_flags_t events);
-static void pmain_io_free(pa_io_event *e);
-static void pmain_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t cb);
-
-struct pa_time_event {
-  cnode n;
-  struct main_timer t;
-  pa_time_event_cb_t callback;
-  pa_time_event_destroy_cb_t destroy_callback;
-  void *userdata;
-  struct timeval tv;
-};
-
-static clist pmain_time_gc_list;
-
-static pa_time_event *pmain_time_new(pa_mainloop_api *api, const struct timeval *tv, pa_time_event_cb_t cb, void *userdata);
-static void pmain_time_restart(pa_time_event *e, const struct timeval *tv);
-static void pmain_time_free(pa_time_event *e);
-static void pmain_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t cb);
-
-struct pa_defer_event {
-  cnode n;
-  struct main_hook h;
-  pa_defer_event_cb_t callback;
-  pa_defer_event_destroy_cb_t destroy_callback;
-  void *userdata;
-};
-
-static clist pmain_defer_gc_list;
-
-static pa_defer_event *pmain_defer_new(pa_mainloop_api *api, pa_defer_event_cb_t cb, void *userdata);
-static void pmain_defer_enable(pa_defer_event *e, int b);
-static void pmain_defer_free(pa_defer_event *e);
-static void pmain_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t cb);
-
-static void pmain_quit(pa_mainloop_api *a, int retval);
-
-static struct main_hook pmain_gc_hook;
-
-static void pmain_schedule_gc(void);
-
-struct pa_mainloop_api pmain_api = {
-  .io_new = pmain_io_new,
-  .io_enable = pmain_io_enable,
-  .io_free = pmain_io_free,
-  .io_set_destroy = pmain_io_set_destroy,
-
-  .time_new = pmain_time_new,
-  .time_restart = pmain_time_restart,
-  .time_free = pmain_time_free,
-  .time_set_destroy = pmain_time_set_destroy,
-
-  .defer_new = pmain_defer_new,
-  .defer_enable = pmain_defer_enable,
-  .defer_free = pmain_defer_free,
-  .defer_set_destroy = pmain_defer_set_destroy,
-
-  .quit = pmain_quit,
-};
-
-static struct pmain_io *pmain_get_io(int fd)
-{
-  CLIST_FOR_EACH(struct pmain_io *, io, pmain_io_list)
-    if (io->f.fd == fd)
-      {
-       DBG("Pulse: Recycling IO master");
-       return io;
-      }
-
-  struct pmain_io *io = xmalloc_zero(sizeof(*io));
-  io->f.fd = fd;
-  io->f.data = io;
-  clist_add_tail(&pmain_io_list, &io->n);
-  clist_init(&io->io_events);
-  return io;
-}
-
-static pa_io_event *pmain_io_new(pa_mainloop_api *api UNUSED, int fd, pa_io_event_flags_t events, pa_io_event_cb_t cb, void *userdata)
-{
-  struct pa_io_event *e = xmalloc_zero(sizeof(*e));
-  DBG("Pulse: Creating new IO %p for fd %u", e, fd);
-
-  e->io = pmain_get_io(fd);
-  e->callback = cb;
-  e->userdata = userdata;
-  clist_add_head(&e->io->io_events, &e->n);    // Do not call the new IO if created from another IO on the same fd
-  pmain_io_enable(e, events);
-  return e;
-}
-
-static int pmain_io_read(struct main_file *f)
-{
-  struct pmain_io *io = f->data;
-  DBG("Pulse: fd %d ready for read", io->f.fd);
-
-  CLIST_FOR_EACH(struct pa_io_event *, e, io->io_events)
-    if (e->events & PA_IO_EVENT_INPUT)
-      {
-       DBG("Pulse: Callback on IO %p", e);
-       e->callback(&pmain_api, e, io->f.fd, PA_IO_EVENT_INPUT, e->userdata);
-      }
-
-  DBG("Pulse: fd %d read done", io->f.fd);
-  return HOOK_IDLE;
-}
-
-static int pmain_io_write(struct main_file *f)
-{
-  struct pmain_io *io = f->data;
-  DBG("Pulse: fd %d ready for write", io->f.fd);
-
-  CLIST_FOR_EACH(struct pa_io_event *, e, io->io_events)
-    if (e->events & PA_IO_EVENT_OUTPUT)
-      {
-       DBG("Pulse: Callback on IO %p", e);
-       e->callback(&pmain_api, e, io->f.fd, PA_IO_EVENT_OUTPUT, e->userdata);
-      }
-
-  DBG("Pulse: fd %d write done", io->f.fd);
-  return HOOK_IDLE;
-}
-
-static void pmain_io_enable(pa_io_event *e, pa_io_event_flags_t events)
-{
-  struct pmain_io *io = e->io;
-  DBG("Pulse: Changing IO event mask for IO %p on fd %d to %02x", e, io->f.fd, events);
-  e->events = events;
-
-  pa_io_event_flags_t mask = 0;
-  CLIST_FOR_EACH(struct pa_io_event *, f, io->io_events)
-    mask |= f->events;
-  DBG("Pulse: Recalculated IO mask for fd %d to %02x", io->f.fd, mask);
-
-  if (mask)
-    {
-      io->f.read_handler = (mask & PA_IO_EVENT_INPUT) ? pmain_io_read : NULL;
-      io->f.write_handler = (mask & PA_IO_EVENT_OUTPUT) ? pmain_io_write : NULL;
-      if (file_is_active(&io->f))
-       file_chg(&io->f);
-      else
-       file_add(&io->f);
-    }
-  else
-    file_del(&io->f);
-}
-
-static void pmain_io_free(pa_io_event *e)
-{
-  DBG("Pulse: Deleting IO %p for fd %d", e, e->io->f.fd);
-  pmain_io_enable(e, 0);
-  clist_add_tail(&pmain_io_gc_list, &e->gc_n);
-  pmain_schedule_gc();
-}
-
-static void pmain_io_set_destroy(pa_io_event *e, pa_io_event_destroy_cb_t cb)
-{
-  e->destroy_callback = cb;
-}
-
-static void pmain_time_handler(struct main_timer *t)
-{
-  struct pa_time_event *e = t->data;
-  DBG("Pulse: Timer %p triggered", e);
-  timer_del(t);
-  e->callback(&pmain_api, e, &e->tv, e->userdata);
-  DBG("Pulse: Timer %p done", e);
-}
-
-static pa_time_event *pmain_time_new(pa_mainloop_api *api UNUSED, const struct timeval *tv, pa_time_event_cb_t cb, void *userdata)
-{
-  struct pa_time_event *e = xmalloc_zero(sizeof(*e));
-  DBG("Pulse: Creating timer %p", e);
-  e->callback = cb;
-  e->userdata = userdata;
-  e->t.handler = pmain_time_handler;
-  e->t.data = e;
-  pmain_time_restart(e, tv);
-  return e;
-}
-
-static timestamp_t timeval_to_timestamp(const struct timeval *tv)
-{
-  return 1000 * (timestamp_t) tv->tv_sec + tv->tv_usec / 1000;
-}
-
-static void pmain_time_restart(pa_time_event *e, const struct timeval *tv)
-{
-  struct timeval now;
-  gettimeofday(&now, NULL);
-  timestamp_t ts_now = timeval_to_timestamp(&now);
-  timestamp_t ts_fire = timeval_to_timestamp(tv);
-  timestamp_t ts_delta = ts_fire - ts_now;
-  DBG("Pulse: Setting timer %p to %+d", e, (int) ts_delta);
-  timer_del(&e->t);
-  e->tv = *tv;
-  timer_add_rel(&e->t, ts_delta);
-}
-
-static void pmain_time_free(pa_time_event *e)
-{
-  DBG("Pulse: Timer %p deleted", e);
-  timer_del(&e->t);
-  clist_add_tail(&pmain_time_gc_list, &e->n);
-  pmain_schedule_gc();
-}
-
-static void pmain_time_set_destroy(pa_time_event *e, pa_time_event_destroy_cb_t cb)
-{
-  e->destroy_callback = cb;
-}
-
-static int pmain_defer_handler(struct main_hook *h)
-{
-  struct pa_defer_event *e = h->data;
-  DBG("Pulse: Deferred event %p triggered", e);
-  e->callback(&pmain_api, e, e->userdata);
-  DBG("Pulse: Deferred event done");
-  return hook_is_active(&e->h) ? HOOK_RETRY : HOOK_IDLE;
-}
-
-static pa_defer_event *pmain_defer_new(pa_mainloop_api *api UNUSED, pa_defer_event_cb_t cb, void *userdata)
-{
-  struct pa_defer_event *e = xmalloc_zero(sizeof(*e));
-  DBG("Pulse: Creating defer %p", e);
-  e->callback = cb;
-  e->userdata = userdata;
-  e->h.handler = pmain_defer_handler;
-  e->h.data = e;
-  pmain_defer_enable(e, 1);
-  return e;
-}
-
-static void pmain_defer_enable(pa_defer_event *e, int b)
-{
-  DBG("Pulse: %sabling defer %p", (b ? "En" : "Dis"), e);
-  if (b)
-    hook_add(&e->h);
-  else
-    hook_del(&e->h);
-}
-
-static void pmain_defer_free(pa_defer_event *e)
-{
-  DBG("Pulse: Deferred event %p deleted", e);
-  hook_del(&e->h);
-  clist_add_tail(&pmain_defer_gc_list, &e->n);
-  pmain_schedule_gc();
-}
-
-static void pmain_defer_set_destroy(pa_defer_event *e, pa_defer_event_destroy_cb_t cb)
-{
-  e->destroy_callback = cb;
-}
-
-static void pmain_quit(pa_mainloop_api *a UNUSED, int retval UNUSED)
-{
-  DBG("Pulse: Main loop quit not implemented");
-}
-
-static int pmain_gc_handler(struct main_hook *h)
-{
-  DBG("Pulse: Garbage collector");
-  hook_del(h);
-
-  cnode *n;
-  while (n = clist_remove_head(&pmain_io_gc_list))
-    {
-      struct pa_io_event *ei = SKIP_BACK(struct pa_io_event, gc_n, n);
-      struct pmain_io *io = ei->io;
-      DBG("Pulse: GC of IO event %p on fd %d", ei, io->f.fd);
-      if (ei->destroy_callback)
-       ei->destroy_callback(&pmain_api, ei, ei->userdata);
-      clist_remove(&ei->n);
-      if (clist_empty(&io->io_events))
-       {
-         ASSERT(!file_is_active(&io->f));
-         DBG("Pulse: GC of IO master for fd %d", io->f.fd);
-         clist_remove(&io->n);
-         xfree(io);
-       }
-      xfree(ei);
-    }
-
-  struct pa_time_event *et;
-  while (et = (struct pa_time_event *) clist_remove_head(&pmain_time_gc_list))
-    {
-      DBG("Pulse: GC for timer %p", et);
-      if (et->destroy_callback)
-       et->destroy_callback(&pmain_api, et, et->userdata);
-      xfree(et);
-    }
-
-  struct pa_defer_event *ed;
-  while (ed = (struct pa_defer_event *) clist_remove_head(&pmain_defer_gc_list))
-    {
-      DBG("Pulse: GC for defer %p", ed);
-      if (ed->destroy_callback)
-       ed->destroy_callback(&pmain_api, ed, ed->userdata);
-      xfree(ed);
-    }
-
-  DBG("Pulse: Garbage collector done");
-  return HOOK_RETRY;
-}
-
-static void pmain_schedule_gc(void)
-{
-  hook_add(&pmain_gc_hook);
-}
-
-void pmain_init(void)
-{
-  clist_init(&pmain_io_list);
-  clist_init(&pmain_io_gc_list);
-  clist_init(&pmain_time_gc_list);
-  clist_init(&pmain_defer_gc_list);
-  pmain_gc_hook.handler = pmain_gc_handler;
-}
diff --git a/ursaryd/pulse.c b/ursaryd/pulse.c
deleted file mode 100644 (file)
index 21005ba..0000000
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- *     Asynchronous Interface to PulseAudio
- *
- *     (c) 2014 Martin Mares <mj@ucw.cz>
- */
-
-#define LOCAL_DEBUG
-
-#include <ucw/lib.h>
-#include <ucw/clists.h>
-#include <ucw/mainloop.h>
-#include <ucw/stkstring.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "ursaryd.h"
-
-enum pulse_state pulse_state;
-#define PULSE_STATE(s) do { pulse_state = s; DBG("Pulse: " #s); } while (0)
-
-clist pulse_client_list, pulse_sink_list, pulse_sink_input_list;
-
-static pa_context *pulse_ctx;
-static struct main_timer pulse_connect_timer;
-
-/*** Tracking of currently running asynchronous operations ***/
-
-struct pulse_op {
-  cnode n;
-  pa_operation *o;
-  bool is_init;
-};
-
-static clist pulse_op_list;
-
-static struct pulse_op *pulse_op_new(void)
-{
-  struct pulse_op *op = xmalloc_zero(sizeof(*op));
-  clist_add_tail(&pulse_op_list, &op->n);
-  return op;
-}
-
-static void pulse_op_done(struct pulse_op *op)
-{
-  if (op->o)
-    pa_operation_unref(op->o);
-  clist_remove(&op->n);
-  xfree(op);
-}
-
-static void pulse_op_cancel_all(void)
-{
-  struct pulse_op *op;
-  while (op = (struct pulse_op *) clist_head(&pulse_op_list))
-    {
-      DBG("Pulse: Cancelling pending operation");
-      pa_operation_cancel(op->o);
-      pulse_op_done(op);
-    }
-}
-
-#define PULSE_ASYNC_RUN(name, ...) do { struct pulse_op *_op = pulse_op_new(); _op->o = name(pulse_ctx, __VA_ARGS__, _op); } while (0)
-#define PULSE_ASYNC_INIT_RUN(name, ...) do { struct pulse_op *_op = pulse_op_new(); _op->is_init = 1; _op->o = name(pulse_ctx, __VA_ARGS__, _op); } while (0)
-
-static void pulse_success_cb(pa_context *ctx UNUSED, int success, void *userdata)
-{
-  if (!success)
-    msg(L_ERROR, "Pulse: Failure reported");
-  pulse_op_done(userdata);
-}
-
-/*** Debugging dumps ***/
-
-void pulse_dump(void)
-{
-  msg(L_DEBUG, "## Server: default_sink=%s", pulse_default_sink_name);
-
-  CLIST_FOR_EACH(struct pulse_client *, c, pulse_client_list)
-    msg(L_DEBUG, "## Client #%d: %s host=%s", c->idx, c->name, c->host);
-
-  CLIST_FOR_EACH(struct pulse_sink *, s, pulse_sink_list)
-    msg(L_DEBUG, "## Sink #%d: %s channels=%u volume=%u base_vol=%u mute=%u",
-        s->idx, s->name, s->channels, s->volume, s->base_volume, s->mute);
-
-  CLIST_FOR_EACH(struct pulse_sink_input *, s, pulse_sink_input_list)
-    msg(L_DEBUG, "## Sink input #%d: %s client=%d sink=%d channels=%u volume=%u mute=%u",
-        s->idx, s->name, s->client_idx, s->sink_idx, s->channels, s->volume, s->mute);
-}
-
-static void pulse_dump_proplist(pa_proplist *pl UNUSED)
-{
-#if 0
-  void *iterator = NULL;
-  const char *key;
-
-  while (key = pa_proplist_iterate(pl, &iterator))
-    {
-      const char *val = pa_proplist_gets(pl, key);
-      DBG("   %s = %s", key, val);
-    }
-#endif
-}
-
-/*** Server state ***/
-
-char *pulse_default_sink_name;
-
-static void pulse_server_cb(pa_context *ctx UNUSED, const pa_server_info *i, void *userdata)
-{
-  struct pulse_op *op = userdata;
-
-  DBG("Pulse: SERVER default_sink=%s", i->default_sink_name);
-  SET_STRING(pulse_default_sink_name, i->default_sink_name);
-
-  if (op->is_init)
-    {
-      PULSE_STATE(PS_ONLINE);
-      msg(L_INFO, "PulseAudio is ready");
-    }
-  pulse_op_done(op);
-  schedule_update();
-}
-
-void pulse_server_set_default_sink(const char *name)
-{
-  PULSE_ASYNC_RUN(pa_context_set_default_sink, name, pulse_success_cb);
-}
-
-/*** Sink inputs ***/
-
-#define HASH_NODE struct pulse_sink_input
-#define HASH_PREFIX(x) pulse_sink_input_##x
-#define HASH_KEY_ATOMIC idx
-#define HASH_WANT_CLEANUP
-#define HASH_WANT_LOOKUP
-#define HASH_WANT_REMOVE
-#define HASH_ZERO_FILL
-#include <ucw/hashtable.h>
-
-static void pulse_sink_input_cb(pa_context *ctx UNUSED, const pa_sink_input_info *i, int eol, void *userdata)
-{
-  struct pulse_op *op = userdata;
-
-  if (eol)
-    {
-      if (op->is_init)
-       {
-         PULSE_STATE(PS_GET_SERVER);
-         PULSE_ASYNC_INIT_RUN(pa_context_get_server_info, pulse_server_cb);
-       }
-      pulse_op_done(op);
-      return;
-    }
-
-  DBG("Pulse: SINK INPUT #%u: %s client=%d sink=%d chans=%d has_vol=%d vol_rw=%d volume=%u mute=%d",
-    i->index, i->name, i->client, i->sink, i->channel_map.channels, i->has_volume, i->volume_writable, i->volume.values[0], i->mute);
-  pulse_dump_proplist(i->proplist);
-
-  struct pulse_sink_input *s = pulse_sink_input_lookup(i->index);
-  if (!clist_is_linked(&s->n))
-    clist_add_tail(&pulse_sink_input_list, &s->n);
-  SET_STRING(s->name, i->name);
-  s->client_idx = i->client;
-  s->sink_idx = i->sink;
-  s->channels = i->channel_map.channels;
-  s->volume = pa_cvolume_avg(&i->volume);
-  s->mute = i->mute;
-  schedule_update();
-}
-
-static void pulse_sink_input_gone(int idx)
-{
-  DBG("Pulse: REMOVE SINK INPUT #%d", idx);
-  struct pulse_sink_input *s = pulse_sink_input_lookup(idx);
-  clist_remove(&s->n);
-  pulse_sink_input_remove(s);
-  schedule_update();
-}
-
-void pulse_sink_input_set_volume(int idx, pa_cvolume *cvol)
-{
-  PULSE_ASYNC_RUN(pa_context_set_sink_input_volume, idx, cvol, pulse_success_cb);
-}
-
-void pulse_sink_input_set_mute(int idx, bool mute)
-{
-  PULSE_ASYNC_RUN(pa_context_set_sink_input_mute, idx, mute, pulse_success_cb);
-}
-
-void pulse_sink_input_move(int input_idx, int sink_idx)
-{
-  PULSE_ASYNC_RUN(pa_context_move_sink_input_by_index, input_idx, sink_idx, pulse_success_cb);
-}
-
-/*** Sinks ***/
-
-#define HASH_NODE struct pulse_sink
-#define HASH_PREFIX(x) pulse_sink_##x
-#define HASH_KEY_ATOMIC idx
-#define HASH_WANT_CLEANUP
-#define HASH_WANT_LOOKUP
-#define HASH_WANT_REMOVE
-#define HASH_ZERO_FILL
-#include <ucw/hashtable.h>
-
-static void pulse_sink_cb(pa_context *ctx UNUSED, const pa_sink_info *i, int eol, void *userdata)
-{
-  struct pulse_op *op = userdata;
-
-  if (eol)
-    {
-      if (op->is_init)
-       {
-         PULSE_STATE(PS_GET_SINK_INPUTS);
-         PULSE_ASYNC_INIT_RUN(pa_context_get_sink_input_info_list, pulse_sink_input_cb);
-       }
-      pulse_op_done(op);
-      return;
-    }
-
-  DBG("Pulse: SINK #%u: %s (%s) flags=%08x channels=%u volume=%u mute=%d base_vol=%u state=%u",
-    i->index, i->name, i->description, i->flags, i->channel_map.channels, i->volume.values[0], i->mute, i->base_volume, i->state);
-  pulse_dump_proplist(i->proplist);
-
-  struct pulse_sink *s = pulse_sink_lookup(i->index);
-  if (!clist_is_linked(&s->n))
-    clist_add_tail(&pulse_sink_list, &s->n);
-  SET_STRING(s->name, i->name);
-  s->channels = i->channel_map.channels;
-  s->volume = pa_cvolume_avg(&i->volume);
-  s->base_volume = i->base_volume;
-  s->mute = i->mute;
-  schedule_update();
-}
-
-static void pulse_sink_gone(int idx)
-{
-  DBG("Pulse: REMOVE SINK #%d", idx);
-  struct pulse_sink *s = pulse_sink_lookup(idx);
-  clist_remove(&s->n);
-  pulse_sink_remove(s);
-  schedule_update();
-}
-
-struct pulse_sink *pulse_sink_by_name(const char *name)
-{
-  CLIST_FOR_EACH(struct pulse_sink *, s, pulse_sink_list)
-    if (!strcmp(s->name, name))
-      return s;
-  return NULL;
-}
-
-struct pulse_sink *pulse_sink_by_idx(int idx)
-{
-  return pulse_sink_lookup(idx);
-}
-
-void pulse_sink_set_volume(int idx, pa_cvolume *cvol)
-{
-  PULSE_ASYNC_RUN(pa_context_set_sink_volume_by_index, idx, cvol, pulse_success_cb);
-}
-
-void pulse_sink_set_mute(int idx, bool mute)
-{
-  PULSE_ASYNC_RUN(pa_context_set_sink_mute_by_index, idx, mute, pulse_success_cb);
-}
-
-/*** Clients ***/
-
-#define HASH_NODE struct pulse_client
-#define HASH_PREFIX(x) pulse_client_##x
-#define HASH_KEY_ATOMIC idx
-#define HASH_WANT_CLEANUP
-#define HASH_WANT_LOOKUP
-#define HASH_WANT_REMOVE
-#define HASH_ZERO_FILL
-#include <ucw/hashtable.h>
-
-static void pulse_client_cb(pa_context *ctx UNUSED, const pa_client_info *i, int eol, void *userdata)
-{
-  struct pulse_op *op = userdata;
-
-  if (eol)
-    {
-      if (op->is_init)
-       {
-         PULSE_STATE(PS_GET_SINKS);
-         PULSE_ASYNC_INIT_RUN(pa_context_get_sink_info_list, pulse_sink_cb);
-       }
-      pulse_op_done(op);
-      return;
-    }
-
-  char *host = stk_strdup(pa_proplist_gets(i->proplist, "application.process.host") ? : "?");
-  DBG("Pulse: CLIENT #%u: %s mod=%u drv=%s host=%s",
-    i->index, i->name, i->owner_module, i->driver, host);
-  pulse_dump_proplist(i->proplist);
-
-  struct pulse_client *c = pulse_client_lookup(i->index);
-  if (!clist_is_linked(&c->n))
-    clist_add_tail(&pulse_client_list, &c->n);
-  SET_STRING(c->name, i->name);
-  SET_STRING(c->host, host);
-  schedule_update();
-}
-
-static void pulse_client_gone(int idx)
-{
-  DBG("Pulse: REMOVE CLIENT #%d", idx);
-  struct pulse_client *c = pulse_client_lookup(idx);
-  clist_remove(&c->n);
-  pulse_client_remove(c);
-  schedule_update();
-}
-
-struct pulse_client *pulse_client_by_idx(int idx)
-{
-  return pulse_client_lookup(idx);
-}
-
-/*** Events ***/
-
-static void pulse_subscribe_done_cb(pa_context *ctx UNUSED, int success, void *userdata)
-{
-  pulse_op_done(userdata);
-
-  if (!success)
-    msg(L_ERROR, "pa_context_subscribe failed: success=%d", success);
-
-  PULSE_STATE(PS_GET_CLIENTS);
-  PULSE_ASYNC_INIT_RUN(pa_context_get_client_info_list, pulse_client_cb);
-}
-
-static void pulse_event_cb(pa_context *ctx UNUSED, pa_subscription_event_type_t type, uint32_t idx, void *userdata UNUSED)
-{
-  DBG("Pulse: SUBSCRIBE EVENT type=%08x idx=%u", type, idx);
-
-  uint object = type & PA_SUBSCRIPTION_EVENT_FACILITY_MASK;
-  uint action = type & PA_SUBSCRIPTION_EVENT_TYPE_MASK;
-  switch (object)
-    {
-    case PA_SUBSCRIPTION_EVENT_CLIENT:
-      if (action == PA_SUBSCRIPTION_EVENT_NEW || action == PA_SUBSCRIPTION_EVENT_CHANGE)
-       PULSE_ASYNC_RUN(pa_context_get_client_info, idx, pulse_client_cb);
-      else if (action == PA_SUBSCRIPTION_EVENT_REMOVE)
-       pulse_client_gone(idx);
-      break;
-    case PA_SUBSCRIPTION_EVENT_SINK:
-      if (action == PA_SUBSCRIPTION_EVENT_NEW || action == PA_SUBSCRIPTION_EVENT_CHANGE)
-       PULSE_ASYNC_RUN(pa_context_get_sink_info_by_index, idx, pulse_sink_cb);
-      else if (action == PA_SUBSCRIPTION_EVENT_REMOVE)
-       pulse_sink_gone(idx);
-      break;
-    case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
-      if (action == PA_SUBSCRIPTION_EVENT_NEW || action == PA_SUBSCRIPTION_EVENT_CHANGE)
-       PULSE_ASYNC_RUN(pa_context_get_sink_input_info, idx, pulse_sink_input_cb);
-      else if (action == PA_SUBSCRIPTION_EVENT_REMOVE)
-       pulse_sink_input_gone(idx);
-      break;
-    case PA_SUBSCRIPTION_EVENT_SERVER:
-      if (action == PA_SUBSCRIPTION_EVENT_CHANGE)
-       PULSE_ASYNC_RUN(pa_context_get_server_info, pulse_server_cb);
-      break;
-    }
-}
-
-/*** Server state ***/
-
-static void pulse_shutdown(void)
-{
-  DBG("Pulse: Shutting down");
-  pulse_client_cleanup();
-  pulse_sink_cleanup();
-  pulse_sink_input_cleanup();
-}
-
-static void pulse_state_cb(pa_context *ctx, void *userdata UNUSED)
-{
-  int state = pa_context_get_state(ctx);
-  DBG("Pulse: State callback, new state = %d", state);
-  if (state == PA_CONTEXT_READY)
-    {
-      if (pulse_state == PS_OFFLINE)
-       {
-         PULSE_STATE(PS_SUBSCRIBE);
-         pa_context_set_subscribe_callback(ctx, pulse_event_cb, NULL);
-         PULSE_ASYNC_INIT_RUN(pa_context_subscribe, PA_SUBSCRIPTION_MASK_ALL, pulse_subscribe_done_cb);
-       }
-    }
-  else
-    {
-      if (pulse_state != PS_OFFLINE)
-       {
-         msg(L_INFO, "Lost connection to PulseAudio");
-         PULSE_STATE(PS_OFFLINE);
-         pulse_op_cancel_all();
-         pulse_shutdown();
-         schedule_update();
-       }
-      if (state == PA_CONTEXT_FAILED && !timer_is_active(&pulse_connect_timer))
-       timer_add_rel(&pulse_connect_timer, 2000);
-    }
-}
-
-static void pulse_connect(struct main_timer *t)
-{
-  msg(L_DEBUG, "Connecting to PulseAudio");
-  timer_del(t);
-
-  clist_init(&pulse_op_list);
-  clist_init(&pulse_client_list);
-  clist_init(&pulse_sink_list);
-  clist_init(&pulse_sink_input_list);
-  pulse_client_init();
-  pulse_sink_init();
-  pulse_sink_input_init();
-
-  if (pulse_ctx)
-    pa_context_unref(pulse_ctx);
-  pulse_ctx = pa_context_new(&pmain_api, "ursaryd");
-
-  pa_context_set_state_callback(pulse_ctx, pulse_state_cb, NULL);
-  pa_context_connect(pulse_ctx, NULL, PA_CONTEXT_NOAUTOSPAWN, NULL);
-}
-
-void pulse_init(void)
-{
-  pmain_init();
-
-  pulse_connect_timer.handler = pulse_connect;
-  timer_add_rel(&pulse_connect_timer, 0);
-}
diff --git a/ursaryd/ursaryd.c b/ursaryd/ursaryd.c
deleted file mode 100644 (file)
index eaa5654..0000000
+++ /dev/null
@@ -1,575 +0,0 @@
-/*
- *     The Ursary Audio Controls
- *
- *     (c) 2014 Martin Mares <mj@ucw.cz>
- */
-
-#define LOCAL_DEBUG
-
-#include <ucw/lib.h>
-#include <ucw/clists.h>
-#include <ucw/mainloop.h>
-#include <ucw/stkstring.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "ursaryd.h"
-
-/*
- *     Map of all controls
- *
- *             rotary          red button      green button
- *     0       sink Ursarium   mute            select as default (or assign to client selected by touch)
- *     1       sink Catarium   mute            dtto
- *     2       -               -               -
- *     3       -               -               -
- *     4       MPD             mute            play/pause/stop
- *     5       Albireo         mute            -
- *     6       Ogion           mute            -
- *     7       Ursula          mute            -
- *
- *     center  all sinks
- *     slider  -
- */
-
-/*** Sink controls ***/
-
-static double volume_from_pa(pa_volume_t vol)
-{
-  return (double) vol / PA_VOLUME_NORM;
-}
-
-static pa_volume_t volume_to_pa(double vol)
-{
-  return vol * PA_VOLUME_NORM + 0.0001;
-}
-
-static void update_ring_from_sink(int ring, const char *sink_name)
-{
-  struct pulse_sink *s = pulse_sink_by_name(sink_name);
-  if (!s)
-    {
-      noct_set_ring(ring, RING_MODE_SINGLE_ON, 0x7f);
-      noct_set_button(ring, 0);
-      return;
-    }
-
-  if (s->mute)
-    {
-      noct_set_ring(ring, RING_MODE_SINGLE_ON, 0x7f);
-      noct_set_button(ring, 1);
-      return;
-    }
-
-  double vol = CLAMP(volume_from_pa(s->volume), 0, 1);
-  noct_set_ring(ring, RING_MODE_LEFT, CLAMP((int)(0x7f * vol), 12, 0x7f));
-  noct_set_button(ring, 0);
-}
-
-static void update_sink_from_rotary(int delta, const char *sink_name)
-{
-  struct pulse_sink *s = pulse_sink_by_name(sink_name);
-  if (!s)
-    return;
-
-  double vol = volume_from_pa(s->volume) + delta * 0.02;
-  pa_volume_t pavol = volume_to_pa(CLAMP(vol, 0, 1));
-  if (pavol == s->volume)
-    return;
-  pa_cvolume cvol;
-  pa_cvolume_set(&cvol, s->channels, pavol);
-
-  DBG("## Setting volume of sink %s to %d", s->name, cvol.values[0]);
-  pulse_sink_set_volume(s->idx, &cvol);
-}
-
-static void update_sink_mute_from_button(int on, const char *sink_name)
-{
-  if (!on)
-    return;
-
-  struct pulse_sink *s = pulse_sink_by_name(sink_name);
-  if (!s)
-    return;
-
-  DBG("## Setting mute of sink %s to %d", s->name, !s->mute);
-  pulse_sink_set_mute(s->idx, !s->mute);
-}
-
-/*** Client controls ***/
-
-struct client_map {
-  int rotary;
-  const char *client;
-  const char *host;
-  double range;
-};
-
-static struct client_map client_map[] = {
-  { 4, "Music Player Daemon",  "albireo",      1 },
-  { 5, "MPlayer",              NULL,           1 },
-  { 6, NULL,                   "ogion",        1 },
-  { 7, NULL,                   "ursula",       1 },
-};
-
-#define NUM_CLIENTS ARRAY_SIZE(client_map)
-
-struct client_state {
-  double volume;
-  bool have_muted[2];
-};
-
-static struct client_state client_state[NUM_CLIENTS];
-
-static int find_client_by_rotary(int rotary)
-{
-  uns i;
-  for (i=0; i < NUM_CLIENTS; i++)
-    if (client_map[i].rotary == rotary)
-      return i;
-  return -1;
-}
-
-static void calc_clients(void)
-{
-  bzero(client_state, sizeof(client_state));
-
-  CLIST_FOR_EACH(struct pulse_sink_input *, s, pulse_sink_input_list)
-    {
-      s->noct_client_idx = -1;
-
-      if (s->client_idx < 0 || s->sink_idx < 0)
-       continue;
-
-      struct pulse_client *c = pulse_client_by_idx(s->client_idx);
-      if (!c)
-       continue;
-
-      for (uns i=0; i < NUM_CLIENTS; i++)
-       {
-         struct client_map *cm = &client_map[i];
-         struct client_state *cs = &client_state[i];
-         if ((!cm->client || !strcmp(cm->client, c->name)) &&
-             (!cm->host || !strcmp(cm->host, c->host)))
-           {
-             // DBG("@@ Client #%d, sink input #%d -> rotary %d", s->client_idx, s->idx, cm->rotary);
-             s->noct_client_idx = i;
-             cs->volume = MAX(cs->volume, s->volume);
-             cs->have_muted[!!s->mute] = 1;
-             break;
-           }
-       }
-    }
-}
-
-static void update_clients(void)
-{
-  calc_clients();
-
-  for (uns i=0; i < NUM_CLIENTS; i++)
-    {
-      struct client_map *cm = &client_map[i];
-      struct client_state *cs = &client_state[i];
-      if (!cs->have_muted[0] && !cs->have_muted[1])
-       {
-         noct_set_ring(cm->rotary, RING_MODE_LEFT, 0);
-         noct_set_button(cm->rotary, 0);
-       }
-      else if (!cs->have_muted[0])
-       {
-         noct_set_ring(cm->rotary, RING_MODE_SINGLE_ON, 0x7f);
-         noct_set_button(cm->rotary, 1);
-       }
-      else
-       {
-         double vol = CLAMP(volume_from_pa(cs->volume), 0, cm->range);
-         int val = 0x7f * vol / cm->range;
-         val = CLAMP(val, 12, 0x7f);
-         noct_set_ring(cm->rotary, RING_MODE_LEFT, val);
-         noct_set_button(cm->rotary, 0);
-       }
-    }
-}
-
-static void update_client_from_rotary(int rotary, int delta)
-{
-  int i = find_client_by_rotary(rotary);
-  if (i < 0)
-    return;
-  struct client_map *cm = &client_map[i];
-  struct client_state *cs = &client_state[i];
-
-  calc_clients();
-  double vol = volume_from_pa(cs->volume) + delta*0.02;
-  pa_volume_t pavol = volume_to_pa(CLAMP(vol, 0, cm->range));
-
-  CLIST_FOR_EACH(struct pulse_sink_input *, s, pulse_sink_input_list)
-    {
-      if (s->noct_client_idx == i && s->volume != pavol)
-       {
-         DBG("@@ Client #%d, sink input #%d: setting volume=%u", s->client_idx, s->idx, pavol);
-         pa_cvolume cvol;
-         pa_cvolume_set(&cvol, s->channels, pavol);
-         pulse_sink_input_set_volume(s->idx, &cvol);
-       }
-    }
-}
-
-static void update_client_from_button(int button, int on)
-{
-  if (button >= 8 || !on)
-    return;
-
-  int i = find_client_by_rotary(button);
-  if (i < 0)
-    return;
-  struct client_state *cs = &client_state[i];
-
-  calc_clients();
-  if (!cs->have_muted[0] && !cs->have_muted[1])
-    return;
-  uns mute = !cs->have_muted[1];
-
-  CLIST_FOR_EACH(struct pulse_sink_input *, s, pulse_sink_input_list)
-    {
-      if (s->noct_client_idx == i)
-       {
-         DBG("@@ Client #%d, sink input #%d: setting mute=%u", s->client_idx, s->idx, mute);
-         pulse_sink_input_set_mute(s->idx, mute);
-       }
-    }
-}
-
-static int find_touched_client(void)
-{
-  int touched = -1;
-
-  for (uns i=0; i < NUM_CLIENTS; i++)
-    if (noct_rotary_touched[client_map[i].rotary])
-      {
-       if (touched >= 0)
-         return -1;
-       touched = i;
-      }
-  return touched;
-}
-
-/*** Default sink controls ***/
-
-static const char *get_client_sink(int i)
-{
-  const char *sink = NULL;
-
-  CLIST_FOR_EACH(struct pulse_sink_input *, s, pulse_sink_input_list)
-    if (s->noct_client_idx == i)
-      {
-       struct pulse_sink *sk = (s->sink_idx >= 0) ? pulse_sink_by_idx(s->sink_idx) : NULL;
-       const char *ss = sk ? sk->name : NULL;
-       if (!sink)
-         sink = ss;
-       else if (strcmp(sink, ss))
-         sink = "?";
-      }
-  return sink ? : "?";
-}
-
-static void update_default_sink(void)
-{
-  int i = find_touched_client();
-  const char *sink;
-  if (i >= 0)
-    sink = get_client_sink(i);
-  else
-    sink = pulse_default_sink_name ? : "?";
-
-  if (!strcmp(sink, "ursarium"))
-    {
-      noct_set_button(8, 1);
-      noct_set_button(9, 0);
-    }
-  else if (!strcmp(sink, "catarium"))
-    {
-      noct_set_button(8, 0);
-      noct_set_button(9, 1);
-    }
-  else
-    {
-      noct_set_button(8, 0);
-      noct_set_button(9, 0);
-    }
-}
-
-static void update_default_sink_from_button(int button, int on)
-{
-  if (!on)
-    return;
-
-  int i = find_touched_client();
-  const char *sink;
-  if (i >= 0)
-    sink = get_client_sink(i);
-  else
-    sink = pulse_default_sink_name ? : "?";
-
-  const char *switch_to = NULL;
-  if (button == 8)
-    {
-      if (!strcmp(sink, "ursarium"))
-       switch_to = "burrow";
-      else
-       switch_to = "ursarium";
-    }
-  else if (button == 9)
-    {
-      if (!strcmp(sink, "catarium"))
-       switch_to = "burrow";
-      else
-       switch_to = "catarium";
-    }
-
-  if (!switch_to)
-    return;
-
-  if (i >= 0)
-    {
-      struct pulse_sink *sk = pulse_sink_by_name(switch_to);
-      if (!sk)
-       return;
-
-      CLIST_FOR_EACH(struct pulse_sink_input *, s, pulse_sink_input_list)
-        if (s->noct_client_idx == i)
-         {
-           DBG("Moving input #%d to sink #%d", s->idx, sk->idx);
-           pulse_sink_input_move(s->idx, sk->idx);
-         }
-    }
-  else
-    {
-      DBG("Switching default sink to %s", switch_to);
-      pulse_server_set_default_sink(switch_to);
-    }
-}
-
-/*** MPD controls ***/
-
-static bool mpd_flash_state;
-
-static void mpd_flash_timeout(struct main_timer *t)
-{
-  mpd_flash_state ^= 1;
-  noct_set_button(12, mpd_flash_state);
-  timer_add_rel(t, 500);
-}
-
-static struct main_timer mpd_flash_timer = {
-  .handler = mpd_flash_timeout,
-};
-
-static void update_mpd(void)
-{
-  const char *state = mpd_get_player_state();
-  if (!strcmp(state, "play"))
-    {
-      noct_set_button(12, 1);
-      timer_del(&mpd_flash_timer);
-    }
-  else if (!strcmp(state, "pause"))
-    {
-      if (!timer_is_active(&mpd_flash_timer))
-       {
-         mpd_flash_state = 1;
-         mpd_flash_timeout(&mpd_flash_timer);
-       }
-    }
-  else
-    {
-      noct_set_button(12, 0);
-      timer_del(&mpd_flash_timer);
-    }
-}
-
-static void mpd_button_timeout(struct main_timer *t)
-{
-  DBG("MPD stop");
-  timer_del(t);
-  mpd_stop();
-}
-
-static void update_mpd_from_button(int button UNUSED, int on)
-{
-  static struct main_timer mpd_button_timer = {
-    .handler = mpd_button_timeout,
-  };
-
-  const char *state = mpd_get_player_state();
-
-  if (!on)
-    {
-      if (timer_is_active(&mpd_button_timer))
-       {
-         timer_del(&mpd_button_timer);
-         if (!strcmp(state, "play"))
-           {
-             DBG("MPD pause");
-             mpd_pause(1);
-           }
-         else if (!strcmp(state, "pause"))
-           {
-             DBG("MPD resume");
-             mpd_pause(0);
-           }
-       }
-      return;
-    }
-
-  if (!strcmp(state, "stop"))
-    {
-      DBG("MPD play");
-      mpd_play();
-    }
-  else
-    {
-      DBG("MPD starting button timer");
-      timer_add_rel(&mpd_button_timer, 1000);
-    }
-}
-
-/*** Main update routines ***/
-
-static struct main_timer update_timer;
-
-static void do_update(struct main_timer *t)
-{
-  timer_del(t);
-  if (!noct_is_ready())
-    {
-      DBG("## UPDATE: Nocturn is not ready");
-      return;
-    }
-
-  static bool dead;
-  if (pulse_state != PS_ONLINE)
-    {
-      DBG("## UPDATE: Pulse is not online");
-      for (int i=0; i<=8; i++)
-       noct_set_ring(i, RING_MODE_LEFT, 0);
-      for (int i=0; i<8; i++)
-       {
-         noct_set_button(i, 1);
-         noct_set_button(i+8, 0);
-       }
-      dead = 1;
-      return;
-    }
-  if (dead)
-    {
-      DBG("## UPDATE: Waking up from the dead");
-      for (int i=0; i<=8; i++)
-       noct_set_ring(i, RING_MODE_LEFT, 0);
-      for (int i=0; i<16; i++)
-       noct_set_button(i, 0);
-      dead = 0;
-    }
-
-  DBG("## UPDATE");
-#ifdef LOCAL_DEBUG
-  pulse_dump();
-#endif
-
-  update_ring_from_sink(0, "ursarium");
-  update_ring_from_sink(1, "catarium");
-  update_clients();
-  update_default_sink();
-  update_mpd();
-}
-
-void schedule_update(void)
-{
-  timer_add_rel(&update_timer, 10);
-}
-
-void notify_rotary(int rotary, int delta)
-{
-  if (pulse_state != PS_ONLINE)
-    {
-      DBG("## NOTIFY: Pulse is not online");
-      return;
-    }
-
-  switch (rotary)
-    {
-    case 0:
-      update_sink_from_rotary(delta, "ursarium");
-      break;
-    case 1:
-      update_sink_from_rotary(delta, "catarium");
-      break;
-    case 8:
-      update_sink_from_rotary(delta, "ursarium");
-      update_sink_from_rotary(delta, "catarium");
-      break;
-    default:
-      update_client_from_rotary(rotary, delta);
-    }
-}
-
-void notify_button(int button, int on)
-{
-  if (pulse_state != PS_ONLINE)
-    {
-      DBG("## NOTIFY: Pulse is not online");
-      return;
-    }
-
-  switch (button)
-    {
-    case 0:
-      update_sink_mute_from_button(on, "ursarium");
-      break;
-    case 1:
-      update_sink_mute_from_button(on, "catarium");
-      break;
-    case 8:
-    case 9:
-      update_default_sink_from_button(button, on);
-      break;
-    case 12:
-      update_mpd_from_button(button, on);
-      break;
-    default:
-      update_client_from_button(button, on);
-    }
-}
-
-void notify_touch(int rotary, int on UNUSED)
-{
-  if (pulse_state != PS_ONLINE)
-    {
-      DBG("## NOTIFY: Pulse is not online");
-      return;
-    }
-
-  // Rotary touches switch meaning of LEDs, this is handled inside display updates
-  if (rotary >= 4 && rotary < 8)
-    schedule_update();
-}
-
-/*** Main entry point ***/
-
-int main(int argc UNUSED, char **argv)
-{
-  log_init(argv[0]);
-  main_init();
-  update_timer.handler = do_update;
-
-  noct_init();
-  pulse_init();
-  mpd_init();
-
-  msg(L_DEBUG, "Entering main loop");
-  main_loop();
-
-  return 0;
-}
diff --git a/ursaryd/ursaryd.h b/ursaryd/ursaryd.h
deleted file mode 100644 (file)
index ddfc18d..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- *     The Ursary Audio Controls
- *
- *     (c) 2014 Martin Mares <mj@ucw.cz>
- */
-
-#include <pulse/pulseaudio.h>
-
-#define SET_STRING(_field, _val) do { if (!_field || strcmp(_field, _val)) { xfree(_field); _field = xstrdup(_val); } } while (0)
-
-/* ursary.c */
-
-void schedule_update(void);
-
-void notify_rotary(int rotary, int delta);
-void notify_touch(int rotary, int on);
-void notify_button(int button, int on);
-
-/* nocturn.c */
-
-void noct_init(void);
-bool noct_is_ready(void);
-void noct_set_ring(int ring, int mode, int val);
-void noct_set_button(int button, int val);
-
-extern char noct_rotary_touched[10];   // 8=center, 9=slider
-extern char noct_button_pressed[16];
-
-enum ring_mode {
-  RING_MODE_LEFT,
-  RING_MODE_RIGHT,
-  RING_MODE_MID_RIGHT,
-  RING_MODE_MID_SYM,
-  RING_MODE_SINGLE_ON,
-  RING_MODE_SINGLE_OFF,
-};
-
-/* pulse.c */
-
-enum pulse_state {
-  PS_OFFLINE,
-  PS_SUBSCRIBE,
-  PS_GET_CLIENTS,
-  PS_GET_SINKS,
-  PS_GET_SINK_INPUTS,
-  PS_GET_SERVER,
-  PS_ONLINE,
-};
-
-extern enum pulse_state pulse_state;
-extern char *pulse_default_sink_name;
-
-struct pulse_client {
-  cnode n;
-  int idx;
-  char *name;
-  char *host;
-};
-
-struct pulse_sink {
-  cnode n;
-  int idx;
-  char *name;
-  uint channels;
-  uint volume;
-  uint base_volume;
-  int mute;
-};
-
-struct pulse_sink_input {
-  cnode n;
-  int idx;
-  char *name;
-  int client_idx;
-  int sink_idx;
-  uint channels;
-  uint volume;
-  uint mute;
-  int noct_client_idx;         // Used by the high-level logic below
-};
-
-extern clist pulse_client_list, pulse_sink_list, pulse_sink_input_list;
-
-void pulse_init(void);
-void pulse_dump(void);
-struct pulse_sink *pulse_sink_by_name(const char *name);
-struct pulse_sink *pulse_sink_by_idx(int idx);
-void pulse_sink_set_volume(int idx, pa_cvolume *cvol);
-void pulse_sink_set_mute(int idx, bool mute);
-void pulse_sink_input_set_volume(int idx, pa_cvolume *cvol);
-void pulse_sink_input_set_mute(int idx, bool mute);
-void pulse_sink_input_move(int input_idx, int sink_idx);
-struct pulse_client *pulse_client_by_idx(int idx);
-void pulse_server_set_default_sink(const char *name);
-
-/* pulse-ucw.c */
-
-extern struct pa_mainloop_api pmain_api;
-
-void pmain_init(void);
-
-/* mpd.c */
-
-enum mpd_state {
-  MPD_OFFLINE,
-  MPD_CONNECTING,
-  MPD_WAIT_GREETING,
-  MPD_ONLINE,
-};
-
-extern enum mpd_state mpd_state;
-
-void mpd_init(void);
-const char *mpd_get_player_state(void);
-void mpd_play(void);
-void mpd_stop(void);
-void mpd_pause(int arg);