output_embedded.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * Squeezelite for esp32
  3. *
  4. * (c) Sebastien 2019
  5. * Philippe G. 2019, philippe_44@outlook.com
  6. *
  7. * This software is released under the MIT License.
  8. * https://opensource.org/licenses/MIT
  9. *
  10. */
  11. #include "squeezelite.h"
  12. #include "equalizer.h"
  13. #include "Config.h"
  14. extern log_level log_level_from_sys_level(sys_squeezelite_debug_levels level);
  15. extern sys_squeezelite_config* get_profile(const char* name);
  16. static sys_squeezelite_config* config = NULL;
  17. extern unsigned int* get_rates() ;
  18. extern struct outputstate output;
  19. extern struct buffer* outputbuf;
  20. static bool (*slimp_handler_chain)(u8_t* data, int len);
  21. #define FRAME_BLOCK MAX_SILENCE_FRAMES
  22. #define LOCK mutex_lock(outputbuf->mutex)
  23. #define UNLOCK mutex_unlock(outputbuf->mutex)
  24. // output_bt.c
  25. extern void output_init_bt(unsigned rates[]);
  26. extern void output_close_bt(void);
  27. // output_i2s.c
  28. extern void output_init_i2s(unsigned rates[]);
  29. extern bool output_volume_i2s(unsigned left, unsigned right);
  30. extern void output_close_i2s(void);
  31. // controls.c
  32. extern void cli_controls_init(void);
  33. static log_level loglevel;
  34. static bool (*volume_cb)(unsigned left, unsigned right);
  35. static void (*close_cb)(void);
  36. #pragma pack(push, 1)
  37. struct eqlz_packet {
  38. char opcode[4];
  39. };
  40. struct loud_packet {
  41. char opcode[4];
  42. u8_t loudness;
  43. };
  44. #pragma pack(pop)
  45. static bool handler(u8_t* data, int len) {
  46. bool res = true;
  47. if (!strncmp((char*)data, "eqlz", 4)) {
  48. s8_t* gain = (s8_t*)(data + sizeof(struct eqlz_packet));
  49. // update will be done at next opportunity
  50. equalizer_set_gain(gain);
  51. } else if (!strncmp((char*)data, "loud", 4)) {
  52. struct loud_packet* packet = (struct loud_packet*)data;
  53. // update will be done at next opportunity
  54. equalizer_set_loudness(packet->loudness);
  55. } else {
  56. res = false;
  57. }
  58. // chain protocol handlers (bitwise or is fine)
  59. if (*slimp_handler_chain) res |= (*slimp_handler_chain)(data, len);
  60. return res;
  61. }
  62. void output_init_embedded() {
  63. config = get_profile(NULL); // get the active profile
  64. loglevel = log_level_from_sys_level(config->log.output);
  65. LOG_INFO("init device: %s", sys_squeezelite_outputs_name(config->output_type));
  66. // chain handlers
  67. slimp_handler_chain = slimp_handler;
  68. slimp_handler = handler;
  69. // init equalizer before backends
  70. equalizer_init();
  71. memset(&output, 0, sizeof(output));
  72. unsigned int output_buffer = OUTPUTBUF_SIZE;
  73. if(config->buffers.output > 0){
  74. output_buffer = config->buffers.output *1024;
  75. LOG_DEBUG("Found output buffer configuration: %d (%d)",config->buffers.output,output_buffer);
  76. }
  77. else {
  78. LOG_DEBUG("Using default output buffer: %d",output_buffer);
  79. }
  80. output_init_common(loglevel, sys_squeezelite_outputs_name(config->output_type),
  81. output_buffer, get_rates(), config->amp_gpio_timeout);
  82. output.start_frames = FRAME_BLOCK;
  83. #pragma message("Rate delay logic incomplete")
  84. output.rate_delay = 0;
  85. #if CONFIG_BT_SINK
  86. if (config->output_type == sys_squeezelite_outputs_BT) {
  87. LOG_INFO("init Bluetooth");
  88. close_cb = &output_close_bt;
  89. output_init_bt(get_rates());
  90. } else
  91. #endif
  92. {
  93. close_cb = &output_close_i2s;
  94. volume_cb = &output_volume_i2s;
  95. output_init_i2s(get_rates());
  96. }
  97. output_visu_init(loglevel);
  98. LOG_INFO("init completed.");
  99. }
  100. void output_close_embedded(void) {
  101. LOG_INFO("close output");
  102. if (close_cb) (*close_cb)();
  103. output_close_common();
  104. output_visu_close();
  105. }
  106. void set_volume(unsigned left, unsigned right) {
  107. LOG_DEBUG("setting internal gain left: %u right: %u", left, right);
  108. if (!volume_cb || !(*volume_cb)(left, right)) {
  109. LOCK;
  110. output.gainL = left;
  111. output.gainR = right;
  112. UNLOCK;
  113. }
  114. equalizer_set_volume(left, right);
  115. }
  116. bool test_open(const char* device, unsigned rates[], bool userdef_rates) {
  117. memset(rates, 0, MAX_SUPPORTED_SAMPLERATES * sizeof(unsigned));
  118. if (config->output_type == sys_squeezelite_outputs_I2S) {
  119. unsigned _rates[] = {
  120. #if BYTES_PER_FRAME == 4
  121. 192000,
  122. 176400,
  123. #endif
  124. 96000,
  125. 88200,
  126. 48000,
  127. 44100,
  128. 32000,
  129. 24000,
  130. 22050,
  131. 16000,
  132. 12000,
  133. 11025,
  134. 8000,
  135. 0
  136. };
  137. memcpy(rates, _rates, sizeof(_rates));
  138. } else if (config->output_type == sys_squeezelite_outputs_SPDIF) {
  139. unsigned _rates[] = {
  140. 96000, 88200, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 0};
  141. memcpy(rates, _rates, sizeof(_rates));
  142. } else {
  143. rates[0] = 44100;
  144. }
  145. return true;
  146. }
  147. char* output_state_str(void) {
  148. output_state state;
  149. LOCK;
  150. state = output.state;
  151. UNLOCK;
  152. switch (state) {
  153. case OUTPUT_OFF:
  154. return STR(OUTPUT_OFF);
  155. case OUTPUT_STOPPED:
  156. return STR(OUTPUT_STOPPED);
  157. case OUTPUT_BUFFER:
  158. return STR(OUTPUT_BUFFER);
  159. case OUTPUT_RUNNING:
  160. return STR(OUTPUT_RUNNING);
  161. case OUTPUT_PAUSE_FRAMES:
  162. return STR(OUTPUT_PAUSE_FRAMES);
  163. case OUTPUT_SKIP_FRAMES:
  164. return STR(OUTPUT_SKIP_FRAMES);
  165. case OUTPUT_START_AT:
  166. return STR(OUTPUT_START_AT);
  167. default:
  168. return "OUTPUT_UNKNOWN_STATE";
  169. }
  170. }
  171. bool output_stopped(void) {
  172. output_state state;
  173. LOCK;
  174. state = output.state;
  175. UNLOCK;
  176. return state <= OUTPUT_STOPPED;
  177. }