X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=ursaryd.c;h=1d0e5ff4ed56ea8881a1506f44f1a4908d5f048b;hb=HEAD;hp=9d400233cc314c8daca05ce0d699775a781a7687;hpb=b5453f0cb73e3f0cae88809092df648a63587957;p=ursary.git diff --git a/ursaryd.c b/ursaryd.c index 9d40023..1d0e5ff 100644 --- a/ursaryd.c +++ b/ursaryd.c @@ -1,7 +1,7 @@ /* - * The Ursary Audio Controls + * The Ursary Control Panel * - * (c) 2014--2020 Martin Mares + * (c) 2014-2023 Martin Mares */ #undef LOCAL_DEBUG @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -38,11 +39,11 @@ * 6 Albireo Zoom mute MPD prev * 7 eveyrhing else mute MPD next * - * center - + * center rainbow brightness * slider light color temperature */ -#define PCH_SINK "alsa_output.pci-0000_00_1f.3.analog-stereo" +#define PCH_SINK "alsa_output.pci-0000_07_00.6.analog-stereo" #define BT_SINK "bluez_sink.CC_98_8B_D0_8C_06.a2dp_sink" #define LOGI_SOURCE "alsa_input.usb-046d_Logitech_Webcam_C925e_EF163C5F-02.analog-stereo" @@ -376,11 +377,13 @@ static void update_source_buttons(void) if (!source) return; +#if 0 // Disabled for now // if (source->suspended || source->mute) if (source->mute) noct_set_button(2, 0); else noct_set_button(2, 1); +#endif } static void update_source_mute_from_button(int on, const char *source_name) @@ -392,8 +395,10 @@ static void update_source_mute_from_button(int on, const char *source_name) if (!s) return; +#if 0 DBG("## Setting mute of source %s to %d", s->name, !s->mute); pulse_source_set_mute(s->idx, !s->mute); +#endif } /*** MPD controls ***/ @@ -485,56 +490,51 @@ static void update_mpd_from_button(int button UNUSED, int on) static bool lights_on[2]; static double lights_brightness[2]; static double lights_temperature[2]; +static timestamp_t lights_last_update[2]; static void update_lights(void) { - if (!dmx_is_ready()) + for (uint ch=0; ch < 2; ch++) { - noct_set_ring(3, RING_MODE_SINGLE_ON, 0x7f); - noct_set_button(10, 0); - noct_set_button(11, 0); - return; - } - - for (uint i=0; i<2; i++) - { - uint warm, cold; - if (lights_on[i]) + if (lights_on[ch]) { - noct_set_ring(3-i, RING_MODE_LEFT, lights_brightness[i] * 127); - noct_set_button(11-i, 1); - double r = 2; - double x = (exp(r*lights_brightness[i]) - 1) / (exp(r) - 1); - double t = lights_temperature[i]; - double w = 2*x*(1-t); - double c = 2*x*t; - warm = CLAMP((int)(255*w), 0, 255); - cold = CLAMP((int)(255*c), 0, 255); + noct_set_ring(3-ch, RING_MODE_LEFT, lights_brightness[ch] * 127); + noct_set_button(11-ch, 1); } else { - noct_set_ring(3-i, RING_MODE_LEFT, 0); - noct_set_button(11-i, 0); - warm = cold = 0; + noct_set_ring(3-ch, RING_MODE_LEFT, 0); + noct_set_button(11-ch, 0); } - DBG("Lights[%d]: on=%d bri=%.3f temp=%.3f -> warm=%d cold=%d", i, lights_on[i], lights_brightness[i], lights_temperature[i], warm, cold); - dmx_set_pwm(2*i, warm); - dmx_set_pwm(2*i+1, cold); } } +static void send_lights(int ch) +{ + DBG("Lights[%d]: on=%d bri=%.3f temp=%.3f", ch, lights_on[ch], lights_brightness[ch], lights_temperature[ch]); + double b = lights_on[ch] ? lights_brightness[ch] : 0; + double t = lights_on[ch] ? lights_temperature[ch] : 0; + char topic[100], val[100]; + snprintf(topic, sizeof(topic), "burrow/lights/catarium/%s", (ch ? "top" : "bottom")); + snprintf(val, sizeof(val), "%.3f %.3f", b, t); + mqtt_publish(topic, val); + lights_last_update[ch] = main_get_now(); + update_lights(); +} + static void update_lights_from_rotary(int ch, int delta) { if (lights_on[ch]) lights_brightness[ch] = CLAMP(lights_brightness[ch] + 0.015*delta*abs(delta), 0., 1.); - update_lights(); + send_lights(ch); } static void update_lights_from_slider(int value) { lights_temperature[0] = value / 127.; lights_temperature[1] = value / 127.; - update_lights(); + send_lights(0); + send_lights(1); } static void lights_button_timeout(struct main_timer *t) @@ -544,7 +544,7 @@ static void lights_button_timeout(struct main_timer *t) timer_del(t); lights_on[ch] = 1; lights_brightness[ch] = 1; - update_lights(); + send_lights(ch); } static void update_lights_from_button(int ch, int on) @@ -558,13 +558,79 @@ static void update_lights_from_button(int ch, int on) }}; if (on) + timer_add_rel(&lights_button_timer[ch], 500); + else if (timer_is_active(&lights_button_timer[ch])) { + timer_del(&lights_button_timer[ch]); lights_on[ch] = !lights_on[ch]; - update_lights(); - timer_add_rel(&lights_button_timer[ch], 1000); + send_lights(ch); } +} + +static void update_lights_from_ir(int ch, int dir) +{ + if (lights_on[ch]) + lights_brightness[ch] = CLAMP(lights_brightness[ch] + 0.07*dir, 0., 1.); + else if (dir > 0) + { + lights_on[ch] = 1; + lights_brightness[ch] = 1; + } + else + { + lights_on[ch] = 1; + lights_brightness[ch] = 0.05; + } + send_lights(ch); +} + +static void update_lights_on_off_ir(int ch) +{ + lights_on[ch] ^= 1; + send_lights(ch); +} + +static void update_lights_temp_ir(void) +{ + if (!lights_on[0] && !lights_on[1]) + return; + + double t = (lights_temperature[0] + lights_temperature[1]) / 2; + if (t >= 0.66) + t = 0; + else if (t < 0.33) + t = 0.5; else - timer_del(&lights_button_timer[ch]); + t = 1; + lights_temperature[0] = lights_temperature[1] = t; + + send_lights(0); + send_lights(1); +} + +/*** Rainbow ***/ + +static double rainbow_brightness; +static timestamp_t rainbow_last_update; + +static void update_rainbow(void) +{ + noct_set_ring(8, RING_MODE_LEFT, rainbow_brightness * 127); +} + +static void send_rainbow(void) +{ + char val[100]; + snprintf(val, sizeof(val), "%.3f", rainbow_brightness); + mqtt_publish("burrow/lights/rainbow/brightness", val); + rainbow_last_update = main_get_now(); + update_rainbow(); +} + +static void update_rainbow_from_rotary(int delta) +{ + rainbow_brightness = CLAMP(rainbow_brightness + 0.015*delta*abs(delta), 0., 1.); + send_rainbow(); } /*** Main update routines ***/ @@ -672,6 +738,7 @@ static void do_update(struct main_timer *t) update_source_buttons(); update_mpd(); update_lights(); + update_rainbow(); } void schedule_update(void) @@ -716,6 +783,9 @@ void notify_rotary(int rotary, int delta) case 3: update_lights_from_rotary(0, delta); break; + case 8: + update_rainbow_from_rotary(delta); + break; case 9: update_lights_from_slider(delta); break; @@ -780,6 +850,96 @@ void notify_touch(int rotary UNUSED, int on UNUSED) schedule_update(); } +static void notify_ir(const char *key) +{ + DBG("Received IR key %s", key); + + // Lights + if (!strcmp(key, "preset+")) + update_lights_from_ir(1, 1); + else if (!strcmp(key, "preset-")) + update_lights_from_ir(1, -1); + else if (!strcmp(key, "tuning-up")) + update_lights_from_ir(0, 1); + else if (!strcmp(key, "tuning-down")) + update_lights_from_ir(0, -1); + else if (!strcmp(key, "band")) + update_lights_on_off_ir(1); + else if (!strcmp(key, "fm-mode")) + update_lights_on_off_ir(0); + else if (!strcmp(key, "dimmer")) + update_lights_temp_ir(); + + // Player + else if (!strcmp(key, "play")) + mpd_play(); + else if (!strcmp(key, "stop")) + mpd_stop(); + else if (!strcmp(key, "pause")) + mpd_pause(1); + else if (!strcmp(key, "prev-song")) + mpd_prev(); + else if (!strcmp(key, "next-song")) + mpd_next(); + else if (!strcmp(key, "rewind")) + update_sink_from_rotary(-2, PCH_SINK); + else if (!strcmp(key, "ffwd")) + update_sink_from_rotary(2, PCH_SINK); +} + +void notify_mqtt(const char *topic, const char *val) +{ + const char blc[] = "burrow/lights/catarium/"; + if (str_has_prefix(topic, blc)) + { + topic += strlen(blc); + int ch; + if (!strcmp(topic, "top")) + ch = 1; + else if (!strcmp(topic, "bottom")) + ch = 0; + else + return; + + double b, t; + if (sscanf(val, "%lf %lf", &b, &t) != 2) + return; + + timestamp_t now = main_get_now(); + if (!lights_last_update[ch] || lights_last_update[ch] + 1000 < now) + { + DBG("Received foreign light settings"); + if (!b) + lights_on[ch] = 0; + else + { + lights_on[ch] = 1; + lights_brightness[ch] = b; + lights_temperature[ch] = t; + } + update_lights(); + } + } + + if (!strcmp(topic, "burrow/lights/rainbow/brightness")) + { + double b; + if (sscanf(val, "%lf", &b) == 1 && b >= 0 && b <= 1) + { + timestamp_t now = main_get_now(); + if (!rainbow_last_update || rainbow_last_update + 1000 < now) + { + DBG("Received foreign rainbow settings"); + rainbow_brightness = b; + update_rainbow(); + } + } + } + + if (!strcmp(topic, "burrow/control/catarium-ir")) + notify_ir(val); +} + /*** Main entry point ***/ static int debug; @@ -809,9 +969,9 @@ static void daemon_body(struct daemon_params *dp) usb_init(); noct_init(); - dmx_init(); pulse_init(); mpd_init(); + mqtt_init(); static struct main_signal term_sig = { .signum = SIGTERM,