| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -9,6 +9,7 @@ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include <memory> | 
					 | 
					 | 
					 | 
					#include <memory> | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include <variant> | 
					 | 
					 | 
					 | 
					#include <variant> | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					#include "bluetooth_types.hpp" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include "freertos/portmacro.h" | 
					 | 
					 | 
					 | 
					#include "freertos/portmacro.h" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include "freertos/projdefs.h" | 
					 | 
					 | 
					 | 
					#include "freertos/projdefs.h" | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include "lua.h" | 
					 | 
					 | 
					 | 
					#include "lua.h" | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -73,8 +74,31 @@ lua::Property UiState::sBatteryPct{0}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					lua::Property UiState::sBatteryMv{0}; | 
					 | 
					 | 
					 | 
					lua::Property UiState::sBatteryMv{0}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					lua::Property UiState::sBatteryCharging{false}; | 
					 | 
					 | 
					 | 
					lua::Property UiState::sBatteryCharging{false}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					lua::Property UiState::sBluetoothEnabled{false}; | 
					 | 
					 | 
					 | 
					lua::Property UiState::sBluetoothEnabled{ | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    false, [](const lua::LuaValue& val) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (!std::holds_alternative<bool>(val)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (std::get<bool>(val)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        sServices->bluetooth().Enable(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        sServices->bluetooth().SetDeviceDiscovery(true); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        sServices->bluetooth().Disable(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      return true; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    }}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					lua::Property UiState::sBluetoothConnected{false}; | 
					 | 
					 | 
					 | 
					lua::Property UiState::sBluetoothConnected{false}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					lua::Property UiState::sBluetoothPairedDevice{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    std::monostate{}, [](const lua::LuaValue& val) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (std::holds_alternative<drivers::bluetooth::Device>(val)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        auto dev = std::get<drivers::bluetooth::Device>(val); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        sServices->bluetooth().SetPreferredDevice(dev.address); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    }}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					lua::Property UiState::sBluetoothDevices{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    std::vector<drivers::bluetooth::Device>{}}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					lua::Property UiState::sBluetoothScanning{false}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					lua::Property UiState::sPlaybackPlaying{ | 
					 | 
					 | 
					 | 
					lua::Property UiState::sPlaybackPlaying{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    false, [](const lua::LuaValue& val) { | 
					 | 
					 | 
					 | 
					    false, [](const lua::LuaValue& val) { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -99,38 +123,92 @@ lua::Property UiState::sQueueRandom{false}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					lua::Property UiState::sVolumeCurrentPct{ | 
					 | 
					 | 
					 | 
					lua::Property UiState::sVolumeCurrentPct{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    0, [](const lua::LuaValue& val) { | 
					 | 
					 | 
					 | 
					    0, [](const lua::LuaValue& val) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (!std::holds_alternative<int>(val)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      events::Audio().Dispatch(audio::SetVolume{ | 
					 | 
					 | 
					 | 
					      events::Audio().Dispatch(audio::SetVolume{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          .percent = {}, | 
					 | 
					 | 
					 | 
					          .percent = std::get<int>(val), | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          .db = 0, | 
					 | 
					 | 
					 | 
					          .db = {}, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }); | 
					 | 
					 | 
					 | 
					      }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      return false; | 
					 | 
					 | 
					 | 
					      return true; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }}; | 
					 | 
					 | 
					 | 
					    }}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					lua::Property UiState::sVolumeCurrentDb{ | 
					 | 
					 | 
					 | 
					lua::Property UiState::sVolumeCurrentDb{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    0, [](const lua::LuaValue& val) { | 
					 | 
					 | 
					 | 
					    0, [](const lua::LuaValue& val) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (!std::holds_alternative<int>(val)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      events::Audio().Dispatch(audio::SetVolume{ | 
					 | 
					 | 
					 | 
					      events::Audio().Dispatch(audio::SetVolume{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          .percent = {}, | 
					 | 
					 | 
					 | 
					          .percent = {}, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          .db = 0, | 
					 | 
					 | 
					 | 
					          .db = std::get<int>(val), | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }); | 
					 | 
					 | 
					 | 
					      }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      return false; | 
					 | 
					 | 
					 | 
					      return true; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }}; | 
					 | 
					 | 
					 | 
					    }}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					lua::Property UiState::sVolumeLeftBias{ | 
					 | 
					 | 
					 | 
					lua::Property UiState::sVolumeLeftBias{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    0, [](const lua::LuaValue& val) { | 
					 | 
					 | 
					 | 
					    0, [](const lua::LuaValue& val) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (!std::holds_alternative<int>(val)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      events::Audio().Dispatch(audio::SetVolumeBalance{ | 
					 | 
					 | 
					 | 
					      events::Audio().Dispatch(audio::SetVolumeBalance{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          .left_bias = 0, | 
					 | 
					 | 
					 | 
					          .left_bias = std::get<int>(val), | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }); | 
					 | 
					 | 
					 | 
					      }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      return false; | 
					 | 
					 | 
					 | 
					      return true; | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }}; | 
					 | 
					 | 
					 | 
					    }}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					lua::Property UiState::sVolumeLimit{ | 
					 | 
					 | 
					 | 
					lua::Property UiState::sVolumeLimit{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    0, [](const lua::LuaValue& val) { | 
					 | 
					 | 
					 | 
					    0, [](const lua::LuaValue& val) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (!std::holds_alternative<int>(val)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      int limit = std::get<int>(val); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      events::Audio().Dispatch(audio::SetVolumeLimit{ | 
					 | 
					 | 
					 | 
					      events::Audio().Dispatch(audio::SetVolumeLimit{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          .new_limit = 0, | 
					 | 
					 | 
					 | 
					          .limit_db = limit, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      }); | 
					 | 
					 | 
					 | 
					      }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      return true; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    }}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					lua::Property UiState::sDisplayBrightness{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    0, [](const lua::LuaValue& val) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      std::optional<int> brightness = 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      std::visit( | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          [&](auto&& v) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            using T = std::decay_t<decltype(v)>; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            if constexpr (std::is_same_v<T, int>) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					              brightness = v; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          }, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          val); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (!brightness) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        return false; | 
					 | 
					 | 
					 | 
					        return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      sDisplay->SetBrightness(*brightness); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      sServices->nvs().ScreenBrightness(*brightness); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      return true; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }}; | 
					 | 
					 | 
					 | 
					    }}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					lua::Property UiState::sDisplayBrightness{0, [](const lua::LuaValue& val) { | 
					 | 
					 | 
					 | 
					lua::Property UiState::sControlsScheme{ | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                                            sDisplay->SetBrightness(0); | 
					 | 
					 | 
					 | 
					    0, [](const lua::LuaValue& val) { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (!std::holds_alternative<int>(val)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        return false; | 
					 | 
					 | 
					 | 
					        return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      drivers::NvsStorage::InputModes mode; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      switch (std::get<int>(val)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        case 0: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          mode = drivers::NvsStorage::InputModes::kButtonsOnly; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        case 1: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          mode = drivers::NvsStorage::InputModes::kButtonsWithWheel; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        case 2: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          mode = drivers::NvsStorage::InputModes::kDirectionalWheel; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        case 3: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          mode = drivers::NvsStorage::InputModes::kRotatingWheel; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        default: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					          return false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      sServices->nvs().PrimaryInput(mode); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      sInput->mode(mode); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      return true; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }}; | 
					 | 
					 | 
					 | 
					    }}; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					auto UiState::InitBootSplash(drivers::IGpios& gpios) -> bool { | 
					 | 
					 | 
					 | 
					auto UiState::InitBootSplash(drivers::IGpios& gpios) -> bool { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -223,7 +301,29 @@ void UiState::react(const audio::VolumeBalanceChanged& ev) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void UiState::react(const audio::VolumeLimitChanged& ev) { | 
					 | 
					 | 
					 | 
					void UiState::react(const audio::VolumeLimitChanged& ev) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  sVolumeLeftBias.Update(ev.new_limit); | 
					 | 
					 | 
					 | 
					  sVolumeLimit.Update(ev.new_limit_db); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					void UiState::react(const system_fsm::BluetoothEvent& ev) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  auto bt = sServices->bluetooth(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  switch (ev.event) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    case drivers::bluetooth::Event::kKnownDevicesChanged: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      sBluetoothDevices.Update(bt.KnownDevices()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    case drivers::bluetooth::Event::kConnectionStateChanged: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      sBluetoothConnected.Update(bt.IsConnected()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      if (bt.ConnectedDevice()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        sBluetoothPairedDevice.Update(bt.ConnectedDevice().value()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        sBluetoothPairedDevice.Update(std::monostate{}); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    case drivers::bluetooth::Event::kDiscoveryChanged: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      sBluetoothScanning.Update(bt.IsDiscovering()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    case drivers::bluetooth::Event::kPreferredDeviceChanged: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					namespace states { | 
					 | 
					 | 
					 | 
					namespace states { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -245,12 +345,18 @@ void Splash::react(const system_fsm::BootComplete& ev) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  lv_disp_set_theme(NULL, base_theme); | 
					 | 
					 | 
					 | 
					  lv_disp_set_theme(NULL, base_theme); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  themes::Theme::instance()->Apply(); | 
					 | 
					 | 
					 | 
					  themes::Theme::instance()->Apply(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  sDisplay->SetBrightness(sServices->nvs().ScreenBrightness()); | 
					 | 
					 | 
					 | 
					  int brightness = sServices->nvs().ScreenBrightness(); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  sDisplayBrightness.Update(brightness); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					  sDisplay->SetBrightness(brightness); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  auto touchwheel = sServices->touchwheel(); | 
					 | 
					 | 
					 | 
					  auto touchwheel = sServices->touchwheel(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  if (touchwheel) { | 
					 | 
					 | 
					 | 
					  if (touchwheel) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    sInput = std::make_shared<EncoderInput>(sServices->gpios(), **touchwheel); | 
					 | 
					 | 
					 | 
					    sInput = std::make_shared<EncoderInput>(sServices->gpios(), **touchwheel); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    sInput->mode(sServices->nvs().PrimaryInput()); | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    auto mode = sServices->nvs().PrimaryInput(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    sInput->mode(mode); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    sControlsScheme.Update(static_cast<int>(mode)); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    sTask->input(sInput); | 
					 | 
					 | 
					 | 
					    sTask->input(sInput); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } else { | 
					 | 
					 | 
					 | 
					  } else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    ESP_LOGE(kTag, "no input devices initialised!"); | 
					 | 
					 | 
					 | 
					    ESP_LOGE(kTag, "no input devices initialised!"); | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -274,10 +380,12 @@ void Lua::entry() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                                         {"battery_millivolts", &sBatteryMv}, | 
					 | 
					 | 
					 | 
					                                         {"battery_millivolts", &sBatteryMv}, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                                         {"plugged_in", &sBatteryCharging}, | 
					 | 
					 | 
					 | 
					                                         {"plugged_in", &sBatteryCharging}, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                                     }); | 
					 | 
					 | 
					 | 
					                                     }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    sLua->bridge().AddPropertyModule("bluetooth", | 
					 | 
					 | 
					 | 
					    sLua->bridge().AddPropertyModule( | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                                     { | 
					 | 
					 | 
					 | 
					        "bluetooth", { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                         {"enabled", &sBluetoothEnabled}, | 
					 | 
					 | 
					 | 
					                         {"enabled", &sBluetoothEnabled}, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                         {"connected", &sBluetoothConnected}, | 
					 | 
					 | 
					 | 
					                         {"connected", &sBluetoothConnected}, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                         {"paired_device", &sBluetoothPairedDevice}, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                         {"devices", &sBluetoothDevices}, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                     }); | 
					 | 
					 | 
					 | 
					                     }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    sLua->bridge().AddPropertyModule("playback", | 
					 | 
					 | 
					 | 
					    sLua->bridge().AddPropertyModule("playback", | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                                     { | 
					 | 
					 | 
					 | 
					                                     { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -299,6 +407,16 @@ void Lua::entry() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                                         {"limit_db", &sVolumeLimit}, | 
					 | 
					 | 
					 | 
					                                         {"limit_db", &sVolumeLimit}, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                                     }); | 
					 | 
					 | 
					 | 
					                                     }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    sLua->bridge().AddPropertyModule("display", | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                                     { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                                         {"brightness", &sDisplayBrightness}, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                                     }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    sLua->bridge().AddPropertyModule("controls", | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                                     { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                                         {"scheme", &sControlsScheme}, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                                     }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    sLua->bridge().AddPropertyModule( | 
					 | 
					 | 
					 | 
					    sLua->bridge().AddPropertyModule( | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        "backstack", | 
					 | 
					 | 
					 | 
					        "backstack", | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        { | 
					 | 
					 | 
					 | 
					        { | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -311,6 +429,15 @@ void Lua::entry() { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                      {"hide", [&](lua_State* s) { return HideAlert(s); }}, | 
					 | 
					 | 
					 | 
					                      {"hide", [&](lua_State* s) { return HideAlert(s); }}, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                  }); | 
					 | 
					 | 
					 | 
					                  }); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    auto bt = sServices->bluetooth(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    sBluetoothEnabled.Update(bt.IsEnabled()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    sBluetoothConnected.Update(bt.IsConnected()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if (bt.ConnectedDevice()) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      sBluetoothPairedDevice.Update(bt.ConnectedDevice().value()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    sBluetoothDevices.Update(bt.KnownDevices()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    sBluetoothScanning.Update(bt.IsDiscovering()); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    sCurrentScreen.reset(); | 
					 | 
					 | 
					 | 
					    sCurrentScreen.reset(); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    sLua->RunScript("/lua/main.lua"); | 
					 | 
					 | 
					 | 
					    sLua->RunScript("/lua/main.lua"); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |