mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2026-01-27 12:50:49 +03:00
Merge remote-tracking branch 'origin/master' into master-cmake
Conflicts: README.md components/config/config.c components/driver_bt/bt_app_sink.c components/raop/raop.c components/services/audio_controls.c main/platform_esp32.h
This commit is contained in:
@@ -4,18 +4,8 @@
|
||||
* (c) Sebastien 2019
|
||||
* Philippe G. 2019, philippe_44@outlook.com
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -358,7 +358,7 @@ static decode_state alac_decode(void) {
|
||||
return DECODE_COMPLETE;
|
||||
}
|
||||
|
||||
// enough data for coding
|
||||
// is there enough data for decoding
|
||||
if (bytes < block_size) {
|
||||
UNLOCK_S;
|
||||
return DECODE_RUNNING;
|
||||
|
||||
@@ -1,100 +1,231 @@
|
||||
/*
|
||||
* (c) Philippe G. 2019, philippe_44@outlook.com
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "squeezelite.h"
|
||||
#include "config.h"
|
||||
#include "audio_controls.h"
|
||||
|
||||
static log_level loglevel = lINFO;
|
||||
|
||||
#define DOWN_OFS 0x10000
|
||||
#define UP_OFS 0x20000
|
||||
|
||||
// numbers are simply 0..9 but are not used
|
||||
|
||||
// arrow_right.down = 0001000e seems to be missing ...
|
||||
enum { BUTN_POWER_FRONT = 0X0A, BUTN_ARROW_UP, BUTN_ARROW_DOWN, BUTN_ARROW_LEFT, BUTN_KNOB_PUSH, BUTN_SEARCH,
|
||||
BUTN_REW, BUTN_FWD, BUTN_PLAY, BUTN_ADD, BUTN_BRIGHTNESS, BUTN_NOW_PLAYING,
|
||||
BUTN_PAUSE = 0X17, BUTN_BROWSE, BUTN_VOLUP_FRONT, BUTN_VOLDOWN_FRONT, BUTN_SIZE, BUTN_VISUAL, BUTN_VOLUMEMODE,
|
||||
BUTN_PRESET_1 = 0X23, BUTN_PRESET_2, BUTN_PRESET_3, BUTN_PRESET_4, BUTN_PRESET_5, BUTN_PRESET_6, BUTN_SNOOZE,
|
||||
BUTN_KNOB_LEFT = 0X5A, BUTN_KNOB_RIGHT };
|
||||
|
||||
#define BUTN_ARROW_RIGHT BUTN_KNOB_PUSH
|
||||
|
||||
#pragma pack(push, 1)
|
||||
|
||||
struct BUTN_header {
|
||||
char opcode[4];
|
||||
u32_t length;
|
||||
u32_t jiffies;
|
||||
u32_t button;
|
||||
};
|
||||
|
||||
struct IR_header {
|
||||
char opcode[4];
|
||||
u32_t length;
|
||||
u32_t jiffies;
|
||||
u8_t format; // unused
|
||||
u8_t bits; // unused
|
||||
u32_t code;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
static in_addr_t server_ip;
|
||||
static u16_t server_hport;
|
||||
static u16_t server_cport;
|
||||
static u8_t mac[6];
|
||||
static void (*chained_notify)(in_addr_t, u16_t, u16_t);
|
||||
static bool raw_mode;
|
||||
|
||||
static void cli_send_cmd(char *cmd);
|
||||
|
||||
static void lms_volume_up(void) {
|
||||
cli_send_cmd("button volup");
|
||||
/****************************************************************************************
|
||||
* Send BUTN
|
||||
*/
|
||||
static void sendBUTN(int code, bool pressed) {
|
||||
struct BUTN_header pkt_header;
|
||||
|
||||
memset(&pkt_header, 0, sizeof(pkt_header));
|
||||
memcpy(&pkt_header.opcode, "BUTN", 4);
|
||||
|
||||
pkt_header.length = htonl(sizeof(pkt_header) - 8);
|
||||
pkt_header.jiffies = htonl(gettime_ms());
|
||||
pkt_header.button = htonl(code + (pressed ? DOWN_OFS : UP_OFS));
|
||||
|
||||
LOG_INFO("sending BUTN code %04x %s", code, pressed ? "down" : "up");
|
||||
|
||||
LOCK_P;
|
||||
send_packet((uint8_t *) &pkt_header, sizeof(pkt_header));
|
||||
UNLOCK_P;
|
||||
}
|
||||
|
||||
static void lms_volume_down(void) {
|
||||
cli_send_cmd("button voldown");
|
||||
/****************************************************************************************
|
||||
* Send IR
|
||||
*/
|
||||
static void sendIR(u16_t addr, u16_t cmd) {
|
||||
struct IR_header pkt_header;
|
||||
|
||||
memset(&pkt_header, 0, sizeof(pkt_header));
|
||||
memcpy(&pkt_header.opcode, "IR ", 4);
|
||||
|
||||
pkt_header.length = htonl(sizeof(pkt_header) - 8);
|
||||
pkt_header.jiffies = htonl(gettime_ms());
|
||||
pkt_header.format = pkt_header.bits = 0;
|
||||
pkt_header.code = htonl((addr << 16) | cmd);
|
||||
|
||||
LOG_INFO("sending IR code %04x", (addr << 16) | cmd);
|
||||
|
||||
LOCK_P;
|
||||
send_packet((uint8_t *) &pkt_header, sizeof(pkt_header));
|
||||
UNLOCK_P;
|
||||
}
|
||||
|
||||
static void lms_toggle(void) {
|
||||
cli_send_cmd("pause");
|
||||
static void lms_volume_up(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_VOLUP_FRONT, pressed);
|
||||
} else {
|
||||
cli_send_cmd("button volup");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_pause(void) {
|
||||
cli_send_cmd("pause 1");
|
||||
static void lms_volume_down(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_VOLDOWN_FRONT, pressed);
|
||||
} else {
|
||||
cli_send_cmd("button voldown");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_play(void) {
|
||||
cli_send_cmd("button play.single");
|
||||
static void lms_toggle(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_PAUSE, pressed);
|
||||
} else {
|
||||
cli_send_cmd("pause");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_stop(void) {
|
||||
static void lms_pause(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_PAUSE, pressed);
|
||||
} else {
|
||||
cli_send_cmd("pause 1");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_play(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_PLAY, pressed);
|
||||
} else {
|
||||
cli_send_cmd("button play.single");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_stop(bool pressed) {
|
||||
cli_send_cmd("button stop");
|
||||
}
|
||||
|
||||
static void lms_rew(void) {
|
||||
cli_send_cmd("button rew.repeat");
|
||||
static void lms_rew(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_REW, pressed);
|
||||
} else {
|
||||
cli_send_cmd("button rew.repeat");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_fwd(void) {
|
||||
cli_send_cmd("button fwd.repeat");
|
||||
static void lms_fwd(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_FWD, pressed);
|
||||
} else {
|
||||
cli_send_cmd("button fwd.repeat");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_prev(void) {
|
||||
cli_send_cmd("button rew");
|
||||
static void lms_prev(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_REW, pressed);
|
||||
} else {
|
||||
cli_send_cmd("button rew");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_next(void) {
|
||||
cli_send_cmd("button fwd");
|
||||
static void lms_next(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_FWD, pressed);
|
||||
} else {
|
||||
cli_send_cmd("button fwd");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_up(void) {
|
||||
cli_send_cmd("button arrow_up");
|
||||
static void lms_up(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_ARROW_UP, pressed);
|
||||
} else {
|
||||
cli_send_cmd("button arrow_up");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_down(void) {
|
||||
cli_send_cmd("button arrow_down");
|
||||
static void lms_down(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_ARROW_DOWN, pressed);
|
||||
} else {
|
||||
cli_send_cmd("button arrow_down");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_left(void) {
|
||||
cli_send_cmd("button arrow_left");
|
||||
static void lms_left(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_ARROW_LEFT, pressed);
|
||||
} else {
|
||||
cli_send_cmd("button arrow_left");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_right(void) {
|
||||
cli_send_cmd("button arrow_right");
|
||||
static void lms_right(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_ARROW_RIGHT, pressed);
|
||||
} else {
|
||||
cli_send_cmd("button arrow_right");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_knob_left(void) {
|
||||
cli_send_cmd("button knob_left");
|
||||
static void lms_knob_left(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_KNOB_LEFT, pressed);
|
||||
} else {
|
||||
cli_send_cmd("button knob_left");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_knob_right(void) {
|
||||
cli_send_cmd("button knob_right");
|
||||
static void lms_knob_right(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_KNOB_RIGHT, pressed);
|
||||
} else {
|
||||
cli_send_cmd("button knob_right");
|
||||
}
|
||||
}
|
||||
|
||||
static void lms_knob_push(void) {
|
||||
cli_send_cmd("button knob_push");
|
||||
static void lms_knob_push(bool pressed) {
|
||||
if (raw_mode) {
|
||||
sendBUTN(BUTN_KNOB_PUSH, pressed);
|
||||
} else {
|
||||
cli_send_cmd("button knob_push");
|
||||
}
|
||||
}
|
||||
|
||||
const actrls_t LMS_controls = {
|
||||
@@ -143,17 +274,33 @@ static void notify(in_addr_t ip, u16_t hport, u16_t cport) {
|
||||
server_ip = ip;
|
||||
server_hport = hport;
|
||||
server_cport = cport;
|
||||
|
||||
LOG_INFO("notified server %s hport %hu cport %hu", inet_ntoa(ip), hport, cport);
|
||||
|
||||
if (chained_notify) (*chained_notify)(ip, hport, cport);
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* IR handler
|
||||
*/
|
||||
static bool ir_handler(u16_t addr, u16_t cmd) {
|
||||
sendIR(addr, cmd);
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
* Initialize controls - shall be called once from output_init_embedded
|
||||
*/
|
||||
void sb_controls_init(void) {
|
||||
LOG_INFO("initializing CLI controls");
|
||||
char *p = config_alloc_get_default(NVS_TYPE_STR, "lms_ctrls_raw", "n", 0);
|
||||
raw_mode = p && (*p == '1' || *p == 'Y' || *p == 'y');
|
||||
free(p);
|
||||
|
||||
LOG_INFO("initializing audio (buttons/rotary/ir) controls (raw:%u)", raw_mode);
|
||||
|
||||
get_mac(mac);
|
||||
actrls_set_default(LMS_controls, NULL);
|
||||
actrls_set_default(LMS_controls, raw_mode, NULL, ir_handler);
|
||||
|
||||
chained_notify = server_notify;
|
||||
server_notify = notify;
|
||||
}
|
||||
@@ -4,18 +4,8 @@
|
||||
* (c) Sebastien 2019
|
||||
* Philippe G. 2019, philippe_44@outlook.com
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -44,15 +34,15 @@ static bool enable_bt_sink;
|
||||
static bool enable_airplay;
|
||||
|
||||
#define RAOP_OUTPUT_SIZE (RAOP_SAMPLE_RATE * 2 * 2 * 2 * 1.2)
|
||||
#define SYNC_WIN_RUN 32
|
||||
#define SYNC_WIN_SLOW 32
|
||||
#define SYNC_WIN_CHECK 8
|
||||
#define SYNC_WIN_START 2
|
||||
#define SYNC_WIN_FAST 2
|
||||
|
||||
static raop_event_t raop_state;
|
||||
|
||||
static EXT_RAM_ATTR struct {
|
||||
bool enabled;
|
||||
int sum, count, win, errors[SYNC_WIN_RUN];
|
||||
int sum, count, win, errors[SYNC_WIN_SLOW];
|
||||
s32_t len;
|
||||
u32_t start_time, playtime;
|
||||
} raop_sync;
|
||||
@@ -200,48 +190,31 @@ static bool raop_sink_cmd_handler(raop_event_t event, va_list args)
|
||||
// this is async, so player might have been deleted
|
||||
switch (event) {
|
||||
case RAOP_TIMING: {
|
||||
u32_t ms, now = gettime_ms();
|
||||
int error;
|
||||
|
||||
if (!raop_sync.enabled || output.state < OUTPUT_RUNNING || output.frames_played_dmp < output.device_frames) break;
|
||||
|
||||
// first must make sure we started on time
|
||||
if (raop_sync.win == SYNC_WIN_START) {
|
||||
// how many ms have we really played
|
||||
ms = now - output.updated + ((output.frames_played_dmp - output.device_frames) * 10) / (RAOP_SAMPLE_RATE / 100);
|
||||
error = ms - (now - raop_sync.start_time);
|
||||
if (!raop_sync.enabled || output.state != OUTPUT_RUNNING || output.frames_played_dmp < output.device_frames) break;
|
||||
|
||||
u32_t ms, now = gettime_ms();
|
||||
u32_t level = _buf_used(outputbuf);
|
||||
int error;
|
||||
|
||||
LOG_INFO("backend played %u, desired %u, (delta:%d)", ms, now - raop_sync.start_time, error);
|
||||
} else {
|
||||
u32_t level = _buf_used(outputbuf);
|
||||
// in how many ms will the most recent block play
|
||||
ms = (((s32_t)(level - raop_sync.len) / BYTES_PER_FRAME + output.device_frames + output.frames_in_process) * 10) / (RAOP_SAMPLE_RATE / 100) - (s32_t) (now - output.updated);
|
||||
|
||||
// in how many ms will the most recent block play
|
||||
ms = (((s32_t)(level - raop_sync.len) / BYTES_PER_FRAME + output.device_frames + output.frames_in_process) * 10) / (RAOP_SAMPLE_RATE / 100) - (s32_t) (now - output.updated);
|
||||
// when outputbuf is empty, it means we have a network black-out or something
|
||||
error = level ? (raop_sync.playtime - now) - ms : 0;
|
||||
|
||||
// when outputbuf is empty, it means we have a network black-out or something
|
||||
error = level ? (raop_sync.playtime - now) - ms : 0;
|
||||
|
||||
if (loglevel == lDEBUG || !level) {
|
||||
LOG_INFO("head local:%d, remote:%d (delta:%d)", ms, raop_sync.playtime - now, error);
|
||||
LOG_INFO("obuf:%u, sync_len:%u, devframes:%u, inproc:%u", _buf_used(outputbuf), raop_sync.len, output.device_frames, output.frames_in_process);
|
||||
}
|
||||
if (loglevel == lDEBUG || !level) {
|
||||
LOG_INFO("head local:%d, remote:%d (delta:%d)", ms, raop_sync.playtime - now, error);
|
||||
LOG_INFO("obuf:%u, sync_len:%u, devframes:%u, inproc:%u", _buf_used(outputbuf), raop_sync.len, output.device_frames, output.frames_in_process);
|
||||
}
|
||||
|
||||
// calculate sum, error and update sliding window
|
||||
raop_sync.errors[raop_sync.count++ % raop_sync.win] = error;
|
||||
raop_sync.sum += error;
|
||||
error = raop_sync.sum / min(raop_sync.count, raop_sync.win);
|
||||
|
||||
// move to normal mode if possible
|
||||
if (raop_sync.win == SYNC_WIN_START && raop_sync.count >= SYNC_WIN_START && abs(error) < 10) {
|
||||
raop_sync.win = SYNC_WIN_RUN;
|
||||
LOG_INFO("switching to slow sync mode %u", raop_sync.win);
|
||||
}
|
||||
|
||||
// wait till e have enough data or there is a strong deviation
|
||||
if ((raop_sync.count >= raop_sync.win && abs(error) > 10) || (raop_sync.count >= SYNC_WIN_CHECK && abs(error) > 100)) {
|
||||
|
||||
// correct if needed
|
||||
// wait till we have enough data or there is a strong deviation
|
||||
if ((raop_sync.count >= raop_sync.win && abs(error) > 10) || (raop_sync.count >= SYNC_WIN_CHECK && abs(error) > 100)) {
|
||||
if (error < 0) {
|
||||
output.skip_frames = -(error * RAOP_SAMPLE_RATE) / 1000;
|
||||
output.state = OUTPUT_SKIP_FRAMES;
|
||||
@@ -251,11 +224,18 @@ static bool raop_sink_cmd_handler(raop_event_t event, va_list args)
|
||||
output.state = OUTPUT_PAUSE_FRAMES;
|
||||
LOG_INFO("pausing for %u frames (count: %d)", output.pause_frames, raop_sync.count);
|
||||
}
|
||||
|
||||
// reset sliding window
|
||||
|
||||
raop_sync.sum = raop_sync.count = 0;
|
||||
memset(raop_sync.errors, 0, sizeof(raop_sync.errors));
|
||||
|
||||
}
|
||||
|
||||
// move to normal mode if possible
|
||||
if (raop_sync.win == 1) {
|
||||
raop_sync.win = SYNC_WIN_FAST;
|
||||
LOG_INFO("backend played %u, desired %u, (delta:%d)", ms, raop_sync.playtime - now, error);
|
||||
} else if (raop_sync.win == SYNC_WIN_FAST && raop_sync.count >= SYNC_WIN_FAST && abs(error) < 10) {
|
||||
raop_sync.win = SYNC_WIN_SLOW;
|
||||
LOG_INFO("switching to slow sync mode %u", raop_sync.win);
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -272,8 +252,8 @@ static bool raop_sink_cmd_handler(raop_event_t event, va_list args)
|
||||
case RAOP_STREAM:
|
||||
LOG_INFO("Stream", NULL);
|
||||
raop_state = event;
|
||||
raop_sync.win = SYNC_WIN_START;
|
||||
raop_sync.sum = raop_sync.count = 0 ;
|
||||
raop_sync.win = 1;
|
||||
raop_sync.sum = raop_sync.count = 0;
|
||||
memset(raop_sync.errors, 0, sizeof(raop_sync.errors));
|
||||
raop_sync.enabled = !strcasestr(output.device, "BT");
|
||||
output.next_sample_rate = output.current_sample_rate = RAOP_SAMPLE_RATE;
|
||||
|
||||
@@ -1,19 +1,8 @@
|
||||
/*
|
||||
* (c) 2004,2006 Richard Titmuss for SlimProtoLib
|
||||
* (c) Philippe G. 2019, philippe_44@outlook.com
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -208,23 +197,20 @@ extern const uint8_t vu_bitmap[] asm("_binary_vu_data_start");
|
||||
#define ANIM_SCREEN_1 0x04
|
||||
#define ANIM_SCREEN_2 0x08
|
||||
|
||||
static u8_t ANIC_resp = ANIM_NONE;
|
||||
static uint16_t SETD_width;
|
||||
|
||||
#define SCROLL_STACK_SIZE (3*1024)
|
||||
#define LINELEN 40
|
||||
|
||||
static log_level loglevel = lINFO;
|
||||
|
||||
static bool (*slimp_handler_chain)(u8_t *data, int len);
|
||||
static void (*slimp_loop_chain)(void);
|
||||
static void (*notify_chain)(in_addr_t ip, u16_t hport, u16_t cport);
|
||||
static bool (*display_bus_chain)(void *from, enum display_bus_cmd_e cmd);
|
||||
|
||||
#define max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
static void server(in_addr_t ip, u16_t hport, u16_t cport);
|
||||
static void send_server(void);
|
||||
static void sendSETD(u16_t width, u16_t height);
|
||||
static void sendANIC(u8_t code);
|
||||
static bool handler(u8_t *data, int len);
|
||||
static bool display_bus_handler(void *from, enum display_bus_cmd_e cmd);
|
||||
static void vfdc_handler( u8_t *_data, int bytes_read);
|
||||
@@ -234,7 +220,6 @@ static void grfs_handler(u8_t *data, int len);
|
||||
static void grfg_handler(u8_t *data, int len);
|
||||
static void grfa_handler(u8_t *data, int len);
|
||||
static void visu_handler(u8_t *data, int len);
|
||||
|
||||
static void displayer_task(void* arg);
|
||||
|
||||
/* scrolling undocumented information
|
||||
@@ -304,11 +289,13 @@ bool sb_display_init(void) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// inform LMS of our screen dimensions
|
||||
sendSETD(GDS_GetWidth(display), GDS_GetHeight(display));
|
||||
|
||||
// need to force height to 32 maximum
|
||||
displayer.width = GDS_GetWidth(display);
|
||||
displayer.height = min(GDS_GetHeight(display), SB_HEIGHT);
|
||||
SETD_width = displayer.width;
|
||||
|
||||
|
||||
// create visu configuration
|
||||
visu.bar_gap = 1;
|
||||
visu.speed = 100;
|
||||
@@ -330,9 +317,6 @@ bool sb_display_init(void) {
|
||||
slimp_handler_chain = slimp_handler;
|
||||
slimp_handler = handler;
|
||||
|
||||
slimp_loop_chain = slimp_loop;
|
||||
slimp_loop = send_server;
|
||||
|
||||
notify_chain = server_notify;
|
||||
server_notify = server;
|
||||
|
||||
@@ -369,52 +353,44 @@ static bool display_bus_handler(void *from, enum display_bus_cmd_e cmd) {
|
||||
else return true;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************************
|
||||
* Send message to server (ANIC at that time)
|
||||
* Send ANImation Complete
|
||||
*/
|
||||
static void send_server(void) {
|
||||
/*
|
||||
This complication is needed as we cannot send direclty to LMS, because
|
||||
send_packet is not thread safe. So must subscribe to slimproto busy loop
|
||||
end send from there
|
||||
*/
|
||||
if (ANIC_resp != ANIM_NONE) {
|
||||
struct ANIC_header pkt_header;
|
||||
static void sendANIC(u8_t code) {
|
||||
struct ANIC_header pkt_header;
|
||||
|
||||
memset(&pkt_header, 0, sizeof(pkt_header));
|
||||
memcpy(&pkt_header.opcode, "ANIC", 4);
|
||||
pkt_header.length = htonl(sizeof(pkt_header) - 8);
|
||||
pkt_header.mode = ANIC_resp;
|
||||
memset(&pkt_header, 0, sizeof(pkt_header));
|
||||
memcpy(&pkt_header.opcode, "ANIC", 4);
|
||||
pkt_header.length = htonl(sizeof(pkt_header) - 8);
|
||||
pkt_header.mode = code;
|
||||
|
||||
send_packet((uint8_t *) &pkt_header, sizeof(pkt_header));
|
||||
LOCK_P;
|
||||
send_packet((uint8_t *) &pkt_header, sizeof(pkt_header));
|
||||
UNLOCK_P;
|
||||
}
|
||||
|
||||
ANIC_resp = ANIM_NONE;
|
||||
}
|
||||
|
||||
if (SETD_width) {
|
||||
struct SETD_header pkt_header;
|
||||
/****************************************************************************************
|
||||
* Send SETD for width
|
||||
*/
|
||||
static void sendSETD(u16_t width, u16_t height) {
|
||||
struct SETD_header pkt_header;
|
||||
|
||||
memset(&pkt_header, 0, sizeof(pkt_header));
|
||||
memcpy(&pkt_header.opcode, "SETD", 4);
|
||||
memset(&pkt_header, 0, sizeof(pkt_header));
|
||||
memcpy(&pkt_header.opcode, "SETD", 4);
|
||||
|
||||
pkt_header.id = 0xfe; // id 0xfe is width S:P:Squeezebox2
|
||||
pkt_header.length = htonl(sizeof(pkt_header) + 4 - 8);
|
||||
pkt_header.id = 0xfe; // id 0xfe is width S:P:Squeezebox2
|
||||
pkt_header.length = htonl(sizeof(pkt_header) + 4 - 8);
|
||||
|
||||
u16_t height = GDS_GetHeight(display);
|
||||
LOG_INFO("sending dimension %ux%u", SETD_width, height);
|
||||
LOG_INFO("sending dimension %ux%u", width, height);
|
||||
|
||||
SETD_width = htons(SETD_width);
|
||||
height = htons(height);
|
||||
width = htons(width);
|
||||
height = htons(height);
|
||||
|
||||
send_packet((uint8_t *) &pkt_header, sizeof(pkt_header));
|
||||
send_packet((uint8_t *) &SETD_width, 2);
|
||||
send_packet((uint8_t *) &height, 2);
|
||||
|
||||
SETD_width = 0;
|
||||
}
|
||||
|
||||
if (slimp_loop_chain) (*slimp_loop_chain)();
|
||||
LOCK_P;
|
||||
send_packet((uint8_t *) &pkt_header, sizeof(pkt_header));
|
||||
send_packet((uint8_t *) &width, 2);
|
||||
send_packet((uint8_t *) &height, 2);
|
||||
UNLOCK_P;
|
||||
}
|
||||
|
||||
/****************************************************************************************
|
||||
@@ -427,11 +403,13 @@ static void server(in_addr_t ip, u16_t hport, u16_t cport) {
|
||||
|
||||
sprintf(msg, "%s:%hu", inet_ntoa(ip), hport);
|
||||
if (displayer.owned) GDS_TextPos(display, GDS_FONT_DEFAULT, GDS_TEXT_CENTERED, GDS_TEXT_CLEAR | GDS_TEXT_UPDATE, msg);
|
||||
SETD_width = displayer.width;
|
||||
displayer.dirty = true;
|
||||
|
||||
xSemaphoreGive(displayer.mutex);
|
||||
|
||||
// inform new LMS server of our capabilities
|
||||
sendSETD(displayer.width, GDS_GetHeight(display));
|
||||
|
||||
if (notify_chain) (*notify_chain)(ip, hport, cport);
|
||||
}
|
||||
|
||||
@@ -1152,8 +1130,7 @@ static void displayer_task(void *args) {
|
||||
|
||||
// see if we need to pause or if we are done
|
||||
if (scroller.mode) {
|
||||
// can't call directly send_packet from slimproto as it's not re-entrant
|
||||
ANIC_resp = ANIM_SCROLL_ONCE | ANIM_SCREEN_1;
|
||||
sendANIC(ANIM_SCROLL_ONCE | ANIM_SCREEN_1);
|
||||
LOG_INFO("scroll-once terminated");
|
||||
} else {
|
||||
scroller.wake = scroller.pause;
|
||||
|
||||
@@ -4,18 +4,8 @@
|
||||
* (c) Sebastien 2019
|
||||
* Philippe G. 2019, philippe_44@outlook.com
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
#include "squeezelite.h"
|
||||
@@ -25,6 +15,8 @@
|
||||
#include "esp_timer.h"
|
||||
#include "esp_wifi.h"
|
||||
|
||||
mutex_type slimp_mutex;
|
||||
|
||||
void get_mac(u8_t mac[]) {
|
||||
esp_read_mac(mac, ESP_MAC_WIFI_STA);
|
||||
}
|
||||
@@ -56,6 +48,7 @@ extern bool sb_display_init(void);
|
||||
u8_t custom_player_id = 12;
|
||||
|
||||
void embedded_init(void) {
|
||||
mutex_create(slimp_mutex);
|
||||
sb_controls_init();
|
||||
if (sb_display_init()) custom_player_id = 100;
|
||||
}
|
||||
|
||||
@@ -61,6 +61,10 @@ void embedded_init(void);
|
||||
void register_external(void);
|
||||
void deregister_external(void);
|
||||
void decode_restore(int external);
|
||||
// used when other client wants to use slimproto socket to send messages
|
||||
extern mutex_type slimp_mutex;
|
||||
#define LOCK_P mutex_lock(slimp_mutex)
|
||||
#define UNLOCK_P mutex_unlock(slimp_mutex)
|
||||
|
||||
// must provide or define as 0xffff
|
||||
u16_t get_RSSI(void);
|
||||
@@ -80,5 +84,5 @@ void output_visu_close(void);
|
||||
bool (*slimp_handler)(u8_t *data, int len);
|
||||
void (*slimp_loop)(void);
|
||||
void (*server_notify)(in_addr_t ip, u16_t hport, u16_t cport);
|
||||
|
||||
|
||||
#endif // EMBEDDED_H
|
||||
|
||||
@@ -3,18 +3,8 @@
|
||||
*
|
||||
* (c) Philippe G. 2020, philippe_44@outlook.com
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -3,18 +3,8 @@
|
||||
*
|
||||
* (c) Philippe G. 2020, philippe_44@outlook.com
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
14
components/squeezelite/external/dac_external.c
vendored
14
components/squeezelite/external/dac_external.c
vendored
@@ -4,18 +4,8 @@
|
||||
* (c) Sebastien 2019
|
||||
* Philippe G. 2019, philippe_44@outlook.com
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -330,7 +330,7 @@ static decode_state helixaac_decode(void) {
|
||||
u8_t *sptr;
|
||||
bool endstream;
|
||||
frames_t frames;
|
||||
|
||||
|
||||
LOCK_S;
|
||||
bytes_total = _buf_used(streambuf);
|
||||
bytes_wrap = min(bytes_total, _buf_cont_read(streambuf));
|
||||
@@ -389,19 +389,25 @@ static decode_state helixaac_decode(void) {
|
||||
}
|
||||
|
||||
if (found == 1) {
|
||||
|
||||
LOG_INFO("samplerate: %u channels: %u", samplerate, channels);
|
||||
bytes_total = _buf_used(streambuf);
|
||||
bytes_wrap = min(bytes_total, _buf_cont_read(streambuf));
|
||||
|
||||
LOCK_O;
|
||||
LOG_INFO("setting track_start");
|
||||
output.next_sample_rate = decode_newstream(samplerate, output.supported_rates);
|
||||
IF_DSD( output.next_fmt = PCM; )
|
||||
output.track_start = outputbuf->writep;
|
||||
if (output.fade_mode) _checkfade(true);
|
||||
decode.new_stream = false;
|
||||
UNLOCK_O;
|
||||
|
||||
LOG_INFO("setting track start, samplerate: %u channels: %u", samplerate, channels);
|
||||
|
||||
bytes_total = _buf_used(streambuf);
|
||||
bytes_wrap = min(bytes_total, _buf_cont_read(streambuf));
|
||||
|
||||
// come back later if we don' thave enough data
|
||||
if (bytes_total < WRAPBUF_LEN) {
|
||||
UNLOCK_S;
|
||||
LOG_INFO("need more audio data");
|
||||
return DECODE_RUNNING;
|
||||
}
|
||||
|
||||
} else if (found == -1) {
|
||||
|
||||
@@ -418,15 +424,15 @@ static decode_state helixaac_decode(void) {
|
||||
}
|
||||
}
|
||||
|
||||
if (bytes_wrap < WRAPBUF_LEN && bytes_total > WRAPBUF_LEN) {
|
||||
// make a local copy of frames which may have wrapped round the end of streambuf
|
||||
// we always have at least WRAPBUF_LEN unless it's the end of a stream
|
||||
if (bytes_wrap < WRAPBUF_LEN) {
|
||||
// build a linear buffer if we are crossing the end of streambuf
|
||||
memcpy(a->wrap_buf, streambuf->readp, bytes_wrap);
|
||||
memcpy(a->wrap_buf + bytes_wrap, streambuf->buf, WRAPBUF_LEN - bytes_wrap);
|
||||
memcpy(a->wrap_buf + bytes_wrap, streambuf->buf, min(WRAPBUF_LEN, bytes_total) - bytes_wrap);
|
||||
|
||||
sptr = a->wrap_buf;
|
||||
bytes = bytes_wrap = WRAPBUF_LEN;
|
||||
bytes = bytes_wrap = min(WRAPBUF_LEN, bytes_total);
|
||||
} else {
|
||||
|
||||
sptr = streambuf->readp;
|
||||
bytes = bytes_wrap;
|
||||
}
|
||||
@@ -442,9 +448,8 @@ static decode_state helixaac_decode(void) {
|
||||
bytes = bytes_wrap - bytes;
|
||||
endstream = false;
|
||||
|
||||
// mp4 end of chunk - skip to next offset
|
||||
if (a->chunkinfo && a->chunkinfo[a->nextchunk].offset && a->sample++ == a->chunkinfo[a->nextchunk].sample) {
|
||||
|
||||
// mp4 end of chunk - skip to next offset
|
||||
if (a->chunkinfo[a->nextchunk].offset > a->pos) {
|
||||
u32_t skip = a->chunkinfo[a->nextchunk].offset - a->pos;
|
||||
if (skip != bytes) {
|
||||
@@ -461,15 +466,12 @@ static decode_state helixaac_decode(void) {
|
||||
LOG_ERROR("error: need to skip backwards!");
|
||||
endstream = true;
|
||||
}
|
||||
|
||||
// adts and mp4 when not at end of chunk
|
||||
} else if (bytes > 0) {
|
||||
|
||||
// adts and mp4 when not at end of chunk
|
||||
_buf_inc_readp(streambuf, bytes);
|
||||
a->pos += bytes;
|
||||
|
||||
// error which doesn't advance streambuf - end
|
||||
} else {
|
||||
// error which doesn't advance streambuf - end
|
||||
endstream = true;
|
||||
}
|
||||
|
||||
@@ -517,7 +519,7 @@ static decode_state helixaac_decode(void) {
|
||||
frames_t f;
|
||||
frames_t count;
|
||||
ISAMPLE_T *optr;
|
||||
|
||||
|
||||
IF_DIRECT(
|
||||
f = _buf_cont_write(outputbuf) / BYTES_PER_FRAME;
|
||||
optr = (ISAMPLE_T *)outputbuf->writep;
|
||||
@@ -559,7 +561,7 @@ static decode_state helixaac_decode(void) {
|
||||
if (frames) LOG_ERROR("unhandled case");
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
UNLOCK_O_direct;
|
||||
|
||||
return DECODE_RUNNING;
|
||||
@@ -570,13 +572,15 @@ static void helixaac_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
|
||||
|
||||
a->type = size;
|
||||
a->pos = a->consume = a->sample = a->nextchunk = 0;
|
||||
|
||||
|
||||
if (a->chunkinfo) {
|
||||
free(a->chunkinfo);
|
||||
}
|
||||
|
||||
if (a->stsc) {
|
||||
free(a->stsc);
|
||||
}
|
||||
|
||||
a->chunkinfo = NULL;
|
||||
a->stsc = NULL;
|
||||
a->skip = 0;
|
||||
@@ -585,12 +589,14 @@ static void helixaac_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
|
||||
a->empty = false;
|
||||
|
||||
if (a->hAac) {
|
||||
HAAC(a, FlushCodec, a->hAac);
|
||||
// always free decoder as flush only works when no parameter has changed
|
||||
HAAC(a, FreeDecoder, a->hAac);
|
||||
} else {
|
||||
a->hAac = HAAC(a, InitDecoder);
|
||||
a->write_buf = malloc(FRAME_BUF * BYTES_PER_FRAME);
|
||||
a->wrap_buf = malloc(WRAPBUF_LEN);
|
||||
}
|
||||
|
||||
a->hAac = HAAC(a, InitDecoder);
|
||||
}
|
||||
|
||||
static void helixaac_close(void) {
|
||||
|
||||
@@ -4,18 +4,8 @@
|
||||
* (c) Sebastien 2019
|
||||
* Philippe G. 2019, philippe_44@outlook.com
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -4,18 +4,8 @@
|
||||
* (c) Sebastien 2019
|
||||
* Philippe G. 2019, philippe_44@outlook.com
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
#include "squeezelite.h"
|
||||
|
||||
@@ -4,18 +4,8 @@
|
||||
* (c) Sebastien 2019
|
||||
* Philippe G. 2019, philippe_44@outlook.com
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -67,6 +67,10 @@ event_event wake_e;
|
||||
#define UNLOCK_O mutex_unlock(outputbuf->mutex)
|
||||
#define LOCK_D mutex_lock(decode.mutex)
|
||||
#define UNLOCK_D mutex_unlock(decode.mutex)
|
||||
#if !EMBEDDED
|
||||
#define LOCK_P
|
||||
#define UNLOCK_P
|
||||
#endif
|
||||
#if IR
|
||||
#define LOCK_I mutex_lock(ir.mutex)
|
||||
#define UNLOCK_I mutex_unlock(ir.mutex)
|
||||
@@ -149,11 +153,12 @@ static void sendHELO(bool reconnect, const char *fixed_cap, const char *var_cap,
|
||||
LOG_INFO("mac: %02x:%02x:%02x:%02x:%02x:%02x", pkt.mac[0], pkt.mac[1], pkt.mac[2], pkt.mac[3], pkt.mac[4], pkt.mac[5]);
|
||||
|
||||
LOG_INFO("cap: %s%s%s", base_cap, fixed_cap, var_cap);
|
||||
|
||||
LOCK_P;
|
||||
send_packet((u8_t *)&pkt, sizeof(pkt));
|
||||
send_packet((u8_t *)base_cap, strlen(base_cap));
|
||||
send_packet((u8_t *)fixed_cap, strlen(fixed_cap));
|
||||
send_packet((u8_t *)var_cap, strlen(var_cap));
|
||||
UNLOCK_P;
|
||||
}
|
||||
|
||||
static void sendSTAT(const char *event, u32_t server_timestamp) {
|
||||
@@ -205,7 +210,9 @@ static void sendSTAT(const char *event, u32_t server_timestamp) {
|
||||
ms_played - now + status.stream_start, status.device_frames * 1000 / status.current_sample_rate, now - status.updated);
|
||||
}
|
||||
|
||||
LOCK_P;
|
||||
send_packet((u8_t *)&pkt, sizeof(pkt));
|
||||
UNLOCK_P;
|
||||
}
|
||||
|
||||
static void sendDSCO(disconnect_code disconnect) {
|
||||
@@ -218,7 +225,9 @@ static void sendDSCO(disconnect_code disconnect) {
|
||||
|
||||
LOG_DEBUG("DSCO: %d", disconnect);
|
||||
|
||||
LOCK_P;
|
||||
send_packet((u8_t *)&pkt, sizeof(pkt));
|
||||
UNLOCK_P;
|
||||
}
|
||||
|
||||
static void sendRESP(const char *header, size_t len) {
|
||||
@@ -229,9 +238,11 @@ static void sendRESP(const char *header, size_t len) {
|
||||
pkt_header.length = htonl(sizeof(pkt_header) + len - 8);
|
||||
|
||||
LOG_DEBUG("RESP");
|
||||
|
||||
|
||||
LOCK_P;
|
||||
send_packet((u8_t *)&pkt_header, sizeof(pkt_header));
|
||||
send_packet((u8_t *)header, len);
|
||||
UNLOCK_P;
|
||||
}
|
||||
|
||||
static void sendMETA(const char *meta, size_t len) {
|
||||
@@ -243,8 +254,10 @@ static void sendMETA(const char *meta, size_t len) {
|
||||
|
||||
LOG_DEBUG("META");
|
||||
|
||||
LOCK_P;
|
||||
send_packet((u8_t *)&pkt_header, sizeof(pkt_header));
|
||||
send_packet((u8_t *)meta, len);
|
||||
UNLOCK_P;
|
||||
}
|
||||
|
||||
static void sendSETDName(const char *name) {
|
||||
@@ -258,8 +271,10 @@ static void sendSETDName(const char *name) {
|
||||
|
||||
LOG_DEBUG("set playername: %s", name);
|
||||
|
||||
LOCK_P;
|
||||
send_packet((u8_t *)&pkt_header, sizeof(pkt_header));
|
||||
send_packet((u8_t *)name, strlen(name) + 1);
|
||||
UNLOCK_P;
|
||||
}
|
||||
|
||||
#if IR
|
||||
@@ -274,8 +289,9 @@ void sendIR(u32_t code, u32_t ts) {
|
||||
pkt.ir_code = htonl(code);
|
||||
|
||||
LOG_DEBUG("IR: ir code: 0x%x ts: %u", code, ts);
|
||||
|
||||
LOCK_P;
|
||||
send_packet((u8_t *)&pkt, sizeof(pkt));
|
||||
UNLOCK_P;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -4,18 +4,8 @@
|
||||
* (c) Sebastien 2019
|
||||
* Philippe G. 2019, philippe_44@outlook.com
|
||||
*
|
||||
* 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 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
* This software is released under the MIT License.
|
||||
* https://opensource.org/licenses/MIT
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user