initial refactoring

This commit is contained in:
Sebastien L
2023-12-04 23:25:57 -05:00
parent d03678ea81
commit c0ddf0a997
331 changed files with 29663 additions and 16553 deletions

View File

@@ -1,6 +1,6 @@
# for the forgetful, REQUIRES cannot use CONFIG_XXX due to parsing order
if(IDF_TARGET STREQUAL "esp32")
set(target_requires "driver_bt")
set(target_requires "driver_bt" "platform_config")
endif()
idf_component_register( SRC_DIRS . external ac101 tas57xx wm8978

View File

@@ -32,7 +32,7 @@
#include <driver/i2s.h>
#include "adac.h"
#include "ac101.h"
#include "Configurator.h"
static const char TAG[] = "AC101";
#define SPKOUT_EN ((1 << 9) | (1 << 11) | (1 << 7) | (1 << 5))
@@ -54,7 +54,7 @@ static void headset(bool active);
static bool volume(unsigned left, unsigned right);
static void power(adac_power_e mode);
const struct adac_s dac_ac101 = { "AC101", init, adac_deinit, power, speaker, headset, volume };
const struct adac_s dac_ac101 = { sys_DACModelEnum_AC101, init, adac_deinit, power, speaker, headset, volume };
static void ac101_start(ac_module_t mode);
static void ac101_stop(void);

View File

@@ -12,11 +12,11 @@
#include "freertos/FreeRTOS.h"
#include "driver/i2s.h"
#include "driver/i2c.h"
#include "Configurator.h"
typedef enum { ADAC_ON = 0, ADAC_STANDBY, ADAC_OFF } adac_power_e;
struct adac_s {
char *model;
sys_DACModelEnum model;
bool (*init)(char *config, int i2c_port_num, i2s_config_t *i2s_config, bool *mck);
void (*deinit)(void);
void (*power)(adac_power_e mode);

View File

@@ -7,7 +7,8 @@
*/
#include "squeezelite.h"
#include "platform_config.h"
// #include "Configurator.h"
#pragma message("fixme: look for TODO below")
#include "audio_controls.h"
static log_level loglevel = lINFO;
@@ -242,15 +243,16 @@ static bool ir_handler(u16_t addr, u16_t cmd) {
* Initialize controls - shall be called once from output_init_embedded
*/
void sb_controls_init(void) {
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);
// TODO: Add support for the commented code
// 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);
// LOG_INFO("initializing audio (buttons/rotary/ir) controls (raw:%u)", raw_mode);
get_mac(mac);
actrls_set_default(LMS_controls, raw_mode, NULL, ir_handler);
// get_mac(mac);
// actrls_set_default(LMS_controls, raw_mode, NULL, ir_handler);
chained_notify = server_notify;
server_notify = notify;
// chained_notify = server_notify;
// server_notify = notify;
}

View File

@@ -20,6 +20,7 @@
#include "adac.h"
#include "stdio.h"
#include "math.h"
#include "Configurator.h"
#define CS4265_PULL_UP (0x4F )
#define CS4265_PULL_DOWN (0x4E )
@@ -36,7 +37,7 @@ static bool volume(unsigned left, unsigned right);
static void power(adac_power_e mode);
static esp_err_t cs4265_update_bit(uint8_t reg_no,uint8_t mask,uint8_t val );
static esp_err_t set_clock();
const struct adac_s dac_cs4265 = { "CS4265", init, adac_deinit, power, speaker, headset, volume };
const struct adac_s dac_cs4265 = { sys_DACModelEnum_CS4265, init, adac_deinit, power, speaker, headset, volume };
struct cs4265_cmd_s {
uint8_t reg;

View File

@@ -14,7 +14,8 @@
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
#endif
#include "platform_config.h"
#include "Configurator.h"
#include "accessors.h"
#include "squeezelite.h"
@@ -38,6 +39,7 @@ static bool enable_airplay;
#define SYNC_WIN_FAST 2
static raop_event_t raop_state;
static sys_Squeezelite * squeezelite;
static EXT_RAM_ATTR struct {
bool enabled;
@@ -446,44 +448,45 @@ static bool cspot_cmd_handler(cspot_event_t cmd, va_list args)
* We provide the generic codec register option
*/
void register_external(void) {
char *p;
sys_BluetoothSink * bt_sink;
sys_AirPlay * airplay;
sys_Spotify * spotify;
#if CONFIG_BT_SINK
if ((p = config_alloc_get(NVS_TYPE_STR, "enable_bt_sink")) != NULL) {
enable_bt_sink = !strcmp(p,"1") || !strcasecmp(p,"y");
free(p);
if (!strcasestr(output.device, "BT") && enable_bt_sink) {
enable_bt_sink= (SYS_SERVICES_BTSINK(bt_sink) && bt_sink->enabled);
if ( enable_bt_sink) {
#pragma message ("Is the BT sink logic correct?")
if(SYS_SERVICES_SQUEEZELITE(squeezelite) && squeezelite->output_type == sys_OutputTypeEnum_OUTPUT_Bluetooth ){
LOG_ERROR("BT Sink cannot be enabled with Bluetooth output");
}
else {
bt_sink_init(bt_sink_cmd_handler, bt_sink_data_handler);
}
}
}
}
#endif
#if CONFIG_AIRPLAY_SINK
if ((p = config_alloc_get(NVS_TYPE_STR, "enable_airplay")) != NULL) {
enable_airplay = !strcmp(p,"1") || !strcasecmp(p,"y");
free(p);
if (enable_airplay){
raop_sink_init(raop_sink_cmd_handler, raop_sink_data_handler);
LOG_INFO("Initializing AirPlay sink");
}
enable_airplay = SYS_SERVICES_AIRPLAY(airplay) && airplay->enabled;
if (enable_airplay){
raop_sink_init(raop_sink_cmd_handler, raop_sink_data_handler);
LOG_INFO("Initializing AirPlay sink");
}
#endif
#if CONFIG_CSPOT_SINK
if ((p = config_alloc_get(NVS_TYPE_STR, "enable_cspot")) != NULL) {
enable_cspot = strcmp(p,"1") == 0 || strcasecmp(p,"y") == 0;
free(p);
if (enable_cspot){
cspot_sink_init(cspot_cmd_handler, cspot_sink_data_handler);
LOG_INFO("Initializing CSpot sink");
}
enable_cspot = SYS_SERVICES_SPOTIFY(spotify) && spotify->enabled;
if (enable_cspot){
cspot_sink_init(cspot_cmd_handler, cspot_sink_data_handler);
LOG_INFO("Initializing CSpot sink");
}
#endif
}
void deregister_external(void) {
#if CONFIG_BT_SINK
if (!strcasestr(output.device, "BT") && enable_bt_sink) {
sys_Squeezelite * squeezelite;
if(SYS_SERVICES_SQUEEZELITE(squeezelite) && squeezelite->output_type != sys_OutputTypeEnum_OUTPUT_Bluetooth && enable_bt_sink ){
bt_sink_deinit();
}
#endif

View File

@@ -17,20 +17,13 @@
#include "esp_wifi.h"
#include "esp_log.h"
#include "monitor.h"
#include "platform_config.h"
#include "Configurator.h"
#include "messaging.h"
#include "gpio_exp.h"
#include "accessors.h"
#ifndef CONFIG_POWER_GPIO_LEVEL
#define CONFIG_POWER_GPIO_LEVEL 1
#endif
static const char TAG[] = "embedded";
static struct {
int gpio, active;
} power_control = { CONFIG_POWER_GPIO, CONFIG_POWER_GPIO_LEVEL };
static sys_GPIO * power=NULL;
extern void sb_controls_init(void);
extern bool sb_displayer_init(void);
@@ -40,16 +33,6 @@ u8_t custom_player_id = 12;
mutex_type slimp_mutex;
static jmp_buf jumpbuf;
#ifndef POWER_LOCKED
static void set_power_gpio(int gpio, char *value) {
if (strcasestr(value, "power")) {
char *p = strchr(value, ':');
if (p) power_control.active = atoi(p + 1);
power_control.gpio = gpio;
}
}
#endif
void get_mac(u8_t mac[]) {
esp_read_mac(mac, ESP_MAC_WIFI_STA);
}
@@ -88,16 +71,13 @@ int embedded_init(void) {
mutex_create(slimp_mutex);
sb_controls_init();
custom_player_id = sb_displayer_init() ? 100 : 101;
#ifndef POWER_LOCKED
parse_set_GPIO(set_power_gpio);
#endif
if (power_control.gpio != -1) {
gpio_pad_select_gpio_x(power_control.gpio);
gpio_set_direction_x(power_control.gpio, GPIO_MODE_OUTPUT);
gpio_set_level_x(power_control.gpio, !power_control.active);
ESP_LOGI(TAG, "setting power GPIO %d (active:%d)", power_control.gpio, power_control.active);
if(SYS_GPIOS_NAME(power,power) && power->pin >= 0){
gpio_pad_select_gpio_x(power->pin);
gpio_set_direction_x(power->pin, GPIO_MODE_OUTPUT);
gpio_set_level_x(power->pin, !power->level);
ESP_LOGI(TAG, "setting power GPIO %d (active:%d)", power->pin, power->level);
}
return setjmp(jumpbuf);
@@ -108,9 +88,9 @@ void embedded_exit(int code) {
}
void powering(bool on) {
if (power_control.gpio != -1) {
if (power->pin != -1) {
ESP_LOGI(TAG, "powering player %s", on ? "ON" : "OFF");
gpio_set_level_x(power_control.gpio, on ? power_control.active : !power_control.active);
gpio_set_level_x(power->pin, on ? power->level : !power->level);
}
}
@@ -131,25 +111,5 @@ u16_t get_battery(void) {
}
void set_name(char *name) {
char *cmd = config_alloc_get(NVS_TYPE_STR, "autoexec1");
char *p, *q;
if (!cmd) return;
if ((p = strstr(cmd, " -n")) != NULL) {
q = p + 3;
// in case some smart dude has a " -" in player's name
while ((q = strstr(q, " -")) != NULL) {
if (!strchr(q, '"') || !strchr(q+1, '"')) break;
q++;
}
if (q) memmove(p, q, strlen(q) + 1);
else *p = '\0';
}
asprintf(&q, "%s -n \"%s\"", cmd, name);
config_set_value(NVS_TYPE_STR, "autoexec1", q);
free(q);
free(cmd);
strncpy(platform->names.squeezelite,name,sizeof(platform->names.squeezelite));
}

View File

@@ -9,7 +9,7 @@
*/
#include "math.h"
#include "platform_config.h"
#include "Configurator.h"
#include "squeezelite.h"
#include "equalizer.h"
#include "esp_equalizer.h"
@@ -20,12 +20,14 @@ static log_level loglevel = lINFO;
static EXT_RAM_ATTR struct {
void *handle;
float loudness, volume;
uint32_t samplerate;
float gain[EQ_BANDS], loudness_gain[EQ_BANDS];
float volume;
float loudness_gain[EQ_BANDS];
bool update;
sys_Equalizer *state;
} equalizer;
#define POLYNOME_COUNT 6
static const float loudness_envelope_coefficients[EQ_BANDS][POLYNOME_COUNT] = {
@@ -67,11 +69,11 @@ static void calculate_loudness(void) {
char trace[EQ_BANDS * 5 + 1];
size_t n = 0;
for (int i = 0; i < EQ_BANDS; i++) {
for (int j = 0; j < POLYNOME_COUNT && equalizer.loudness != 0; j++) {
for (int j = 0; j < POLYNOME_COUNT && equalizer.state->loudness != 0; j++) {
equalizer.loudness_gain[i] +=
loudness_envelope_coefficients[i][j] * pow(equalizer.volume, j);
}
equalizer.loudness_gain[i] *= equalizer.loudness / 2;
equalizer.loudness_gain[i] *= equalizer.state->loudness / 2;
n += sprintf(trace + n, "%.2g%c", equalizer.loudness_gain[i], i < EQ_BANDS ? ',' : '\0');
}
LOG_INFO("loudness %s", trace);
@@ -81,22 +83,20 @@ static void calculate_loudness(void) {
* initialize equalizer
*/
void equalizer_init(void) {
// handle equalizer
char *config = config_alloc_get(NVS_TYPE_STR, "equalizer");
char *p = strtok(config, ", !");
sys_Services * services;
sys_Equalizer blank_eq = sys_Equalizer_init_default;
for (int i = 0; p && i < EQ_BANDS; i++) {
equalizer.gain[i] = atoi(p);
p = strtok(NULL, ", :");
}
free(config);
// handle loudness
config = config_alloc_get(NVS_TYPE_STR, "loudness");
equalizer.loudness = atof(config) / 10.0;
free(config);
equalizer.state = &sys_state->equalizer;
if(!sys_state->has_equalizer ){
sys_state->has_equalizer = true;
if(SYS_SERVICES(services) && services->has_equalizer){
memcpy(equalizer.state,&services->equalizer,sizeof(sys_Equalizer));
}
else {
memcpy(equalizer.state,&blank_eq,sizeof(sys_Equalizer));
}
configurator_raise_state_changed();
}
}
/****************************************************************************************
@@ -135,7 +135,7 @@ void equalizer_set_volume(unsigned left, unsigned right) {
volume = volume / 16.0 * 100.0;
// LMS has the bad habit to send multiple volume commands
if (volume != equalizer.volume && equalizer.loudness) {
if (volume != equalizer.volume && equalizer.state->loudness) {
equalizer.volume = volume;
calculate_loudness();
equalizer.update = true;
@@ -152,15 +152,16 @@ void equalizer_set_gain(int8_t *gain) {
int n = 0;
for (int i = 0; i < EQ_BANDS; i++) {
equalizer.gain[i] = gain[i];
equalizer.state->gains[i] = gain[i];
n += sprintf(config + n, "%d,", gain[i]);
}
config[n-1] = '\0';
config_set_value(NVS_TYPE_STR, "equalizer", config);
// update only if something changed
if (!memcmp(equalizer.gain, gain, EQ_BANDS)) equalizer.update = true;
if (!memcmp(&equalizer.state->gains, gain, EQ_BANDS)) {
equalizer.update = true;
configurator_raise_state_changed();
}
LOG_INFO("equalizer gain %s", config);
#else
@@ -173,13 +174,11 @@ void equalizer_set_gain(int8_t *gain) {
*/
void equalizer_set_loudness(uint8_t loudness) {
#if BYTES_PER_FRAME == 4
char p[4];
itoa(loudness, p, 10);
config_set_value(NVS_TYPE_STR, "loudness", p);
// update loudness gains as a factor of loudness and volume
if (equalizer.loudness != loudness / 10.0) {
equalizer.loudness = loudness / 10.0;
// update loudness gains as a factor of loudness and volume
if (equalizer.state->loudness != loudness / 10.0) {
equalizer.state->loudness = loudness / 10.0;
configurator_raise_state_changed();
calculate_loudness();
equalizer.update = true;
}
@@ -188,6 +187,7 @@ void equalizer_set_loudness(uint8_t loudness) {
#else
LOG_INFO("no equalizer with 32 bits samples");
#endif
}
/****************************************************************************************
@@ -211,7 +211,7 @@ void equalizer_process(uint8_t *buf, uint32_t bytes) {
bool active = false;
for (int i = 0; i < EQ_BANDS; i++) {
float gain = equalizer.gain[i] + equalizer.loudness_gain[i];
float gain = equalizer.state->gains[i] + equalizer.loudness_gain[i];
esp_equalizer_set_band_value(equalizer.handle, gain, i, 0);
esp_equalizer_set_band_value(equalizer.handle, gain, i, 1);
active |= gain != 0;

View File

@@ -0,0 +1,185 @@
/*
* Squeezelite - lightweight headless squeezebox emulator
*
* (c) Adrian Smith 2012-2015, triode1@btinternet.com
* Ralph Irving 2015-2017, ralph_irving@hotmail.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/>.
*
* Additions (c) Paul Hermann, 2015-2017 under the same license terms
* -Control of Raspberry pi GPIO for amplifier power
* -Launch script on power status change from LMS
*/
#include "squeezelite.h"
#include <signal.h>
#include "Configurator.h"
extern bool user_rates;
static unsigned int rates[MAX_SUPPORTED_SAMPLERATES] = {0};
sys_Squeezelite* config;
log_level loglevel = lDEBUG;
static void sighandler(int signum) {
slimproto_stop();
// remove ourselves in case above does not work, second SIGINT will cause non gracefull shutdown
signal(signum, SIG_DFL);
}
unsigned int* get_rates() {
unsigned int ref[] TEST_RATES;
sys_RatesOption* ratescfg = &config->rates;
if (!config->has_rates || ((ratescfg->list_count == 0 || ratescfg->list[0] == 0) &&
ratescfg->min == 0 && ratescfg->max == 0)) {
user_rates = false;
return rates;
}
if (ratescfg->list_count > 0 && ratescfg->list[0] != 0) {
// Sort the rates from the list
for (int i = 0; i < ratescfg->list_count && i < MAX_SUPPORTED_SAMPLERATES; ++i) {
rates[i] = ratescfg->list[i];
}
// Sort logic here if needed
} else {
// Use min and max to determine rates
unsigned int min = ratescfg->min;
unsigned int max = ratescfg->max;
if (max < min) {
unsigned int tmp = max;
max = min;
min = tmp;
}
for (int i = 0, j = 0; i < MAX_SUPPORTED_SAMPLERATES; ++i) {
if (ref[i] <= max && ref[i] >= min) {
rates[j++] = ref[i];
}
}
}
user_rates = true;
return rates;
}
log_level log_level_from_sys_level(sys_DebugLevelEnum level) {
switch (level) {
case sys_DebugLevelEnum_DEFAULT:
return lWARN;
break;
case sys_DebugLevelEnum_INFO:
return lINFO;
break;
case sys_DebugLevelEnum_ERROR:
return lERROR;
break;
case sys_DebugLevelEnum_WARN:
return lWARN;
break;
case sys_DebugLevelEnum_DEBUG:
return lDEBUG;
break;
case sys_DebugLevelEnum_SDEBUG:
return lSDEBUG;
break;
default:
return lWARN;
}
}
void build_codec_string(sys_CodexEnum* list, size_t count, char* buffer, size_t buf_size) {
const char* prefix = STR(sys_CodexEnum) "_c_";
const char* name = NULL;
for (int i = 0; i < count; i++) {
if (i > 0) {
strncat(buffer, ", ", buf_size);
}
name = sys_CodexEnum_name(list[i]) + strlen(prefix);
LOG_INFO("Found codec: %s ", name);
strncat(buffer, name, buf_size);
}
LOG_INFO("Codec list: %s ", buffer);
}
int squeezelite_main_start() {
u8_t mac[6];
unsigned output_buf_size = 0;
char include_codecs[101] = {0};
char exclude_codecs[101] = {0};
config = platform->has_services && platform->services.has_squeezelite
? &platform->services.squeezelite
: NULL;
if (!config) {
LOG_ERROR("Squeezelite not configured");
return -1;
}
int err = embedded_init();
if (err) return err;
get_mac(mac);
unsigned int * rates = get_rates();
signal(SIGINT, sighandler);
signal(SIGTERM, sighandler);
#if defined(SIGQUIT)
signal(SIGQUIT, sighandler);
#endif
#if defined(SIGHUP)
signal(SIGHUP, sighandler);
#endif
output_buf_size = config->buffers.output;
// set the output buffer size if not specified on the command line, take account of resampling
if (!output_buf_size) {
output_buf_size = OUTPUTBUF_SIZE;
if (strlen(config->resample) > 0) {
unsigned scale = 8;
if (rates[0]) {
scale = rates[0] / 44100;
if (scale > 8) scale = 8;
if (scale < 1) scale = 1;
}
output_buf_size *= scale;
}
}
build_codec_string(config->excluded_codex, config->excluded_codex_count, exclude_codecs,
sizeof(exclude_codecs));
build_codec_string(
config->included_codex, config->included_codex, include_codecs, sizeof(include_codecs));
unsigned int stream_buf_size =
config->buffers.stream > 0 ? config->buffers.stream : STREAMBUF_SIZE;
stream_init(
log_level_from_sys_level(platform->services.squeezelite.log.stream), stream_buf_size);
output_init_embedded();
decode_init(log_level_from_sys_level(platform->services.squeezelite.log.decode), include_codecs,
exclude_codecs);
#if RESAMPLE || RESAMPLE16
if (strlen(config->resample) > 0) {
process_init(config->resample);
}
#endif
if (!config->enabled) {
LOG_ERROR("LMS is disabled");
while (1)
sleep(3600);
}
char* name = strlen(platform->names.squeezelite) > 0 ? platform->names.squeezelite
: platform->names.device;
slimproto(log_level_from_sys_level(platform->services.squeezelite.log.slimproto),
config->server_name_ip, mac, name, NULL, NULL, config->max_rate);
decode_close();
stream_close();
output_close_embedded();
return (0);
}

View File

@@ -16,7 +16,9 @@
#include "esp_log.h"
#include "gpio_exp.h"
#include "cJSON.h"
#include "platform_config.h"
#include "string.h"
// #include "Configurator.h"
#pragma message("fixme: look for TODO below")
#include "adac.h"
static const char TAG[] = "DAC external";
@@ -29,7 +31,7 @@ static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config, bool
static bool i2c_json_execute(char *set);
const struct adac_s dac_external = { "i2s", init, adac_deinit, power, speaker, headset, volume };
const struct adac_s dac_external = { sys_DACModelEnum_I2S, init, adac_deinit, power, speaker, headset, volume };
static cJSON *i2c_json;
static int i2c_addr;
@@ -58,34 +60,35 @@ static const struct {
* init
*/
static bool init(char *config, int i2c_port_num, i2s_config_t *i2s_config, bool *mck) {
char *p;
char *p=NULL;
void * dummy = &codecs;
// i2c_addr = adac_init(config, i2c_port_num);
// if (!i2c_addr) return true;
i2c_addr = adac_init(config, i2c_port_num);
if (!i2c_addr) return true;
// ESP_LOGI(TAG, "DAC on I2C @%d", i2c_addr);
ESP_LOGI(TAG, "DAC on I2C @%d", i2c_addr);
p = config_alloc_get_str("dac_controlset", CONFIG_DAC_CONTROLSET, NULL);
// p = config_alloc_get_str("dac_controlset", CONFIG_DAC_CONTROLSET, NULL);
if ((!p || !*p) && (p = strcasestr(config, "model")) != NULL) {
char model[32] = "";
int i;
sscanf(p, "%*[^=]=%31[^,]", model);
for (i = 0; *model && ((p = codecs[i].controlset) != NULL) && strcasecmp(codecs[i].model, model); i++);
if (p) *mck = codecs[i].mclk;
}
// if ((!p || !*p) && (p = strcasestr(config, "model")) != NULL) {
// char model[32] = "";
// int i;
// sscanf(p, "%*[^=]=%31[^,]", model);
// for (i = 0; *model && ((p = codecs[i].controlset) != NULL) && strcasecmp(codecs[i].model, model); i++);
// if (p) *mck = codecs[i].mclk;
// }
i2c_json = cJSON_Parse(p);
// i2c_json = cJSON_Parse(p);
if (!i2c_json) {
ESP_LOGW(TAG, "no i2c controlset found");
return true;
}
// if (!i2c_json) {
// ESP_LOGW(TAG, "no i2c controlset found");
// return true;
// }
if (!i2c_json_execute("init")) {
ESP_LOGE(TAG, "could not intialize DAC");
return false;
}
// if (!i2c_json_execute("init")) {
// ESP_LOGE(TAG, "could not intialize DAC");
// return false;
// }
// TODO: Add support for the commented code
return true;
}

View File

@@ -767,7 +767,7 @@ int squeezelite_main(int argc, char **argv) {
stream_init(log_stream, stream_buf_size);
#if EMBEDDED
output_init_embedded(log_output, output_device, output_buf_size, output_params, rates, rate_delay, idle);
output_init_embedded();
#else
if (!strcmp(output_device, "-")) {
output_init_stdout(log_output, output_buf_size, output_params, rates, rate_delay);

View File

@@ -14,10 +14,11 @@
#include "squeezelite.h"
#include "equalizer.h"
#include "perf_trace.h"
#include "platform_config.h"
#include "services.h"
#include "led.h"
#include "Configurator.h"
extern log_level log_level_from_sys_level(sys_DebugLevelEnum level);
static sys_Squeezelite * config = NULL;
extern struct outputstate output;
extern struct buffer *outputbuf;
extern struct buffer *streambuf;
@@ -32,7 +33,7 @@ extern u8_t *silencebuf;
#define STATS_REPORT_DELAY_MS 15000
extern void hal_bluetooth_init(const char * options);
extern void hal_bluetooth_init();
extern void hal_bluetooth_stop(void);
extern u8_t config_spdif_gpio;
@@ -74,11 +75,10 @@ static uint32_t bt_idle_callback(void) {
/****************************************************************************************
* Init BT sink
*/
void output_init_bt(log_level level, char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay, unsigned idle) {
loglevel = level;
// idle counter
bt_idle_since = pdTICKS_TO_MS(xTaskGetTickCount());
void output_init_bt() {
config = &platform->services.squeezelite;
loglevel = log_level_from_sys_level(config->log.output);
bt_idle_since = pdTICKS_TO_MS(xTaskGetTickCount());
services_sleep_setsleeper(bt_idle_callback);
// even BT has a right to use led :-)
@@ -86,11 +86,11 @@ void output_init_bt(log_level level, char *device, unsigned output_buf_size, cha
running = true;
output.write_cb = &_write_frames;
hal_bluetooth_init(device);
char *p = config_alloc_get_default(NVS_TYPE_STR, "stats", "n", 0);
stats = p && (*p == '1' || *p == 'Y' || *p == 'y');
free(p);
hal_bluetooth_init();
stats = platform->services.statistics;
equalizer_set_samplerate(output.current_sample_rate);
}
/****************************************************************************************

View File

@@ -1,4 +1,4 @@
/*
/*
* Squeezelite for esp32
*
* (c) Sebastien 2019
@@ -10,27 +10,30 @@
*/
#include "squeezelite.h"
#include "equalizer.h"
#include "Configurator.h"
extern log_level log_level_from_sys_level(sys_DebugLevelEnum level);
static sys_Squeezelite* config = NULL;
extern unsigned int* get_rates() ;
extern struct outputstate output;
extern struct buffer *outputbuf;
extern struct buffer* outputbuf;
static bool (*slimp_handler_chain)(u8_t *data, int len);
static bool (*slimp_handler_chain)(u8_t* data, int len);
#define FRAME_BLOCK MAX_SILENCE_FRAMES
#define LOCK mutex_lock(outputbuf->mutex)
#define LOCK mutex_lock(outputbuf->mutex)
#define UNLOCK mutex_unlock(outputbuf->mutex)
// output_bt.c
extern void output_init_bt(log_level level, char *device, unsigned output_buf_size, char *params,
unsigned rates[], unsigned rate_delay, unsigned idle);
extern void output_close_bt(void);
extern void output_init_bt(unsigned rates[]);
extern void output_close_bt(void);
// output_i2s.c
extern void output_init_i2s(log_level level, char *device, unsigned output_buf_size, char *params,
unsigned rates[], unsigned rate_delay, unsigned idle);
extern bool output_volume_i2s(unsigned left, unsigned right);
extern void output_close_i2s(void);
extern void output_init_i2s(unsigned rates[]);
extern bool output_volume_i2s(unsigned left, unsigned right);
extern void output_close_i2s(void);
// controls.c
extern void cli_controls_init(void);
@@ -42,137 +45,152 @@ static void (*close_cb)(void);
#pragma pack(push, 1)
struct eqlz_packet {
char opcode[4];
char opcode[4];
};
struct loud_packet {
char opcode[4];
u8_t loudness;
char opcode[4];
u8_t loudness;
};
#pragma pack(pop)
static bool handler(u8_t *data, int len){
bool res = true;
if (!strncmp((char*) data, "eqlz", 4)) {
s8_t *gain = (s8_t*) (data + sizeof(struct eqlz_packet));
// update will be done at next opportunity
equalizer_set_gain(gain);
} else if (!strncmp((char*) data, "loud", 4)) {
struct loud_packet *packet = (struct loud_packet*) data;
// update will be done at next opportunity
equalizer_set_loudness(packet->loudness);
} else {
res = false;
}
// chain protocol handlers (bitwise or is fine)
if (*slimp_handler_chain) res |= (*slimp_handler_chain)(data, len);
return res;
static bool handler(u8_t* data, int len) {
bool res = true;
if (!strncmp((char*)data, "eqlz", 4)) {
s8_t* gain = (s8_t*)(data + sizeof(struct eqlz_packet));
// update will be done at next opportunity
equalizer_set_gain(gain);
} else if (!strncmp((char*)data, "loud", 4)) {
struct loud_packet* packet = (struct loud_packet*)data;
// update will be done at next opportunity
equalizer_set_loudness(packet->loudness);
} else {
res = false;
}
// chain protocol handlers (bitwise or is fine)
if (*slimp_handler_chain) res |= (*slimp_handler_chain)(data, len);
return res;
}
void output_init_embedded(log_level level, char *device, unsigned output_buf_size, char *params,
unsigned rates[], unsigned rate_delay, unsigned idle) {
loglevel = level;
LOG_INFO("init device: %s", device);
// chain handlers
slimp_handler_chain = slimp_handler;
slimp_handler = handler;
// init equalizer before backends
equalizer_init();
memset(&output, 0, sizeof(output));
output_init_common(level, device, output_buf_size, rates, idle);
output.start_frames = FRAME_BLOCK;
output.rate_delay = rate_delay;
#if CONFIG_BT_SINK
if (strcasestr(device, "BT")) {
LOG_INFO("init Bluetooth");
close_cb = &output_close_bt;
output_init_bt(level, device, output_buf_size, params, rates, rate_delay, idle);
} else
#endif
{
LOG_INFO("init I2S/SPDIF");
close_cb = &output_close_i2s;
volume_cb = &output_volume_i2s;
output_init_i2s(level, device, output_buf_size, params, rates, rate_delay, idle);
}
output_visu_init(level);
LOG_INFO("init completed.");
}
void output_init_embedded() {
config = &platform->services.squeezelite;
loglevel = log_level_from_sys_level(config->log.output);
LOG_INFO("init device: %s", sys_OutputTypeEnum_name(config->output_type));
// chain handlers
slimp_handler_chain = slimp_handler;
slimp_handler = handler;
// init equalizer before backends
equalizer_init();
memset(&output, 0, sizeof(output));
output_init_common(loglevel, sys_OutputTypeEnum_name(config->output_type),
config->buffers.output, get_rates(), config->amp_gpio_timeout);
output.start_frames = FRAME_BLOCK;
#pragma message("Rate delay logic incomplete")
output.rate_delay = 0;
#if CONFIG_BT_SINK
if (config->output_type == sys_OutputTypeEnum_OUTPUT_Bluetooth) {
LOG_INFO("init Bluetooth");
close_cb = &output_close_bt;
output_init_bt(get_rates());
} else
#endif
{
close_cb = &output_close_i2s;
volume_cb = &output_volume_i2s;
output_init_i2s(get_rates());
}
output_visu_init(loglevel);
LOG_INFO("init completed.");
}
void output_close_embedded(void) {
LOG_INFO("close output");
if (close_cb) (*close_cb)();
output_close_common();
output_visu_close();
LOG_INFO("close output");
if (close_cb) (*close_cb)();
output_close_common();
output_visu_close();
}
void set_volume(unsigned left, unsigned right) {
LOG_DEBUG("setting internal gain left: %u right: %u", left, right);
if (!volume_cb || !(*volume_cb)(left, right)) {
LOCK;
output.gainL = left;
output.gainR = right;
UNLOCK;
}
void set_volume(unsigned left, unsigned right) {
LOG_DEBUG("setting internal gain left: %u right: %u", left, right);
if (!volume_cb || !(*volume_cb)(left, right)) {
LOCK;
output.gainL = left;
output.gainR = right;
UNLOCK;
}
equalizer_set_volume(left, right);
}
bool test_open(const char *device, unsigned rates[], bool userdef_rates) {
memset(rates, 0, MAX_SUPPORTED_SAMPLERATES * sizeof(unsigned));
if (!strcasecmp(device, "I2S")) {
unsigned _rates[] = {
#if BYTES_PER_FRAME == 4
192000, 176400,
#endif
96000, 88200, 48000,
44100, 32000, 24000, 22050, 16000,
12000, 11025, 8000, 0 };
memcpy(rates, _rates, sizeof(_rates));
} else if (!strcasecmp(device, "SPDIF")) {
unsigned _rates[] = { 96000, 88200, 48000,
44100, 32000, 24000, 22050, 16000,
12000, 11025, 8000, 0 };
memcpy(rates, _rates, sizeof(_rates));
} else {
rates[0] = 44100;
}
return true;
bool test_open(const char* device, unsigned rates[], bool userdef_rates) {
memset(rates, 0, MAX_SUPPORTED_SAMPLERATES * sizeof(unsigned));
if (config->output_type == sys_OutputTypeEnum_OUTPUT_I2S) {
unsigned _rates[] = {
#if BYTES_PER_FRAME == 4
192000,
176400,
#endif
96000,
88200,
48000,
44100,
32000,
24000,
22050,
16000,
12000,
11025,
8000,
0
};
memcpy(rates, _rates, sizeof(_rates));
} else if (config->output_type == sys_OutputTypeEnum_OUTPUT_SPDIF) {
unsigned _rates[] = {
96000, 88200, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 0};
memcpy(rates, _rates, sizeof(_rates));
} else {
rates[0] = 44100;
}
return true;
}
char* output_state_str(void){
output_state state;
LOCK;
state = output.state;
UNLOCK;
switch (state) {
case OUTPUT_OFF: return STR(OUTPUT_OFF);
case OUTPUT_STOPPED: return STR(OUTPUT_STOPPED);
case OUTPUT_BUFFER: return STR(OUTPUT_BUFFER);
case OUTPUT_RUNNING: return STR(OUTPUT_RUNNING);
case OUTPUT_PAUSE_FRAMES: return STR(OUTPUT_PAUSE_FRAMES);
case OUTPUT_SKIP_FRAMES: return STR(OUTPUT_SKIP_FRAMES);
case OUTPUT_START_AT: return STR(OUTPUT_START_AT);
default: return "OUTPUT_UNKNOWN_STATE";
}
char* output_state_str(void) {
output_state state;
LOCK;
state = output.state;
UNLOCK;
switch (state) {
case OUTPUT_OFF:
return STR(OUTPUT_OFF);
case OUTPUT_STOPPED:
return STR(OUTPUT_STOPPED);
case OUTPUT_BUFFER:
return STR(OUTPUT_BUFFER);
case OUTPUT_RUNNING:
return STR(OUTPUT_RUNNING);
case OUTPUT_PAUSE_FRAMES:
return STR(OUTPUT_PAUSE_FRAMES);
case OUTPUT_SKIP_FRAMES:
return STR(OUTPUT_SKIP_FRAMES);
case OUTPUT_START_AT:
return STR(OUTPUT_START_AT);
default:
return "OUTPUT_UNKNOWN_STATE";
}
}
bool output_stopped(void) {
output_state state;
LOCK;
state = output.state;
UNLOCK;
return state <= OUTPUT_STOPPED;
}
output_state state;
LOCK;
state = output.state;
UNLOCK;
return state <= OUTPUT_STOPPED;
}

File diff suppressed because it is too large Load Diff

View File

@@ -755,7 +755,7 @@ void _pa_open(void);
#if EMBEDDED
void set_volume(unsigned left, unsigned right);
bool test_open(const char *device, unsigned rates[], bool userdef_rates);
void output_init_embedded(log_level level, char *device, unsigned output_buf_size, char *params, unsigned rates[], unsigned rate_delay, unsigned idle);
void output_init_embedded();
void output_close_embedded(void);
#else
// output_stdout.c

View File

@@ -45,7 +45,7 @@ static void headset(bool active) { } ;
static bool volume(unsigned left, unsigned right);
static void power(adac_power_e mode) { };
const struct adac_s dac_tas5713 = {"TAS5713", init, adac_deinit, power, speaker, headset, volume};
const struct adac_s dac_tas5713 = {sys_DACModelEnum_TAS5713, init, adac_deinit, power, speaker, headset, volume};
struct tas5713_cmd_s {
uint8_t reg;

View File

@@ -29,7 +29,7 @@ static void headset(bool active);
static bool volume(unsigned left, unsigned right);
static void power(adac_power_e mode);
const struct adac_s dac_tas57xx = { "TAS57xx", init, adac_deinit, power, speaker, headset, volume };
const struct adac_s dac_tas57xx = { sys_DACModelEnum_TAS57xx, init, adac_deinit, power, speaker, headset, volume };
struct tas57xx_cmd_s {
uint8_t reg;

View File

@@ -30,7 +30,7 @@ static uint16_t i2c_read_shadow(uint8_t reg);
static int WM8978;
const struct adac_s dac_wm8978 = { "WM8978", init, adac_deinit, power, speaker, headset, volume };
const struct adac_s dac_wm8978 = { sys_DACModelEnum_WM8978, init, adac_deinit, power, speaker, headset, volume };
// initiation table for non-readbale 9-bit i2c registers
static uint16_t WM8978_REGVAL_TBL[58] = {