This commit is contained in:
e2002
2024-12-04 17:58:28 +03:00
parent fd6c1eafd0
commit 001fcb4b93
26 changed files with 679 additions and 110 deletions

View File

@@ -225,11 +225,28 @@ download _http://\<yoradioip\>/data/playlist.csv_ and _http://\<yoradioip\>/data
---
## Plugins
There is no documentation yet, you will have to deal with the examples, which is in directory [examples/plugins/](https://github.com/e2002/yoradio/tree/main/examples/plugins).\
The `Plugin` class serves as a base class for creating plugins that hook into various system events.
To use it, inherit from `Plugin` and override the necessary virtual methods.
Place your new class in the `src/plugins/<MyPlugin>` directory
More details can be found in the comments within the `yoRadio/src/pluginsManager/pluginsManager.h` file and at [here](https://github.com/e2002/yoradio/blob/main/yoRadio/src/pluginsManager/README.md).
Additional examples are provided in the `examples/plugins` folder.
Work is in progress...
---
## Version history
#### v0.9.350
- **Added parameters for configuring `LED_BUILTIN` on ESP32S3 modules:**
- `USE_BUILTIN_LED`: Determines whether to use the built-in `LED_BUILTIN` (default is `true`).
- `LED_BUILTIN_S3`: Specifies a custom pin for the built-in `LED_BUILTIN`. Used in combination with `USE_BUILTIN_LED = false` (default is `255`).
**Note:** For ESP32S3 boards, no changes are required by default; the onboard LED will work as expected.
These settings were added to allow disabling the built-in LED or reassigning it to a custom pin.
- **New class for plugin management**, enabling multiple plugins to be assigned to each function.
More details can be found in the comments within the `yoRadio/src/pluginsManager/pluginsManager.h` file and at [here](https://github.com/e2002/yoradio/blob/main/yoRadio/src/pluginsManager/README.md).
Additional examples are provided in the `examples/plugins` folder.
**Backward compatibility:** The old method of adding plugins will remain functional for some time in future versions but will eventually be deprecated and removed.
#### v0.9.342b
- fixed compilation error for OLED displays

View File

@@ -0,0 +1,46 @@
/**
* Example of display backlight control depending on playback.
* To connect the plugin, copy its folder to the src/plugins directory.
*/
#include "backlightcontrols.h"
#include <Arduino.h>
#include <Ticker.h>
#include "../../core/options.h"
Ticker backlightTicker;
backlightControls blc;
const uint8_t backlightPin = 13;
const uint8_t backlightInitValue = HIGH;
const uint16_t turnBlOffInterval = 120; /* 2 min */
void backlightOff(){
backlightTicker.detach();
digitalWrite(backlightPin, !backlightInitValue);
}
backlightControls::backlightControls() {
registerPlugin();
log_i("Plugin is registered");
}
void backlightControls::on_setup(){
log_i("%s called", __func__ );
pinMode(backlightPin, OUTPUT);
digitalWrite(backlightPin, backlightInitValue);
backlightTicker.attach(turnBlOffInterval, backlightOff);
}
void backlightControls::on_track_change(){
log_i("%s called", __func__ );
digitalWrite(backlightPin, backlightInitValue);
backlightTicker.detach();
backlightTicker.attach(turnBlOffInterval, backlightOff);
}
void backlightControls::on_stop_play(){
log_i("%s called", __func__ );
digitalWrite(backlightPin, backlightInitValue);
backlightTicker.detach();
backlightTicker.attach(turnBlOffInterval, backlightOff);
}

View File

@@ -0,0 +1,23 @@
/**
* Example of display backlight control depending on playback.
* To connect the plugin, copy its folder to the src/plugins directory.
*/
#ifndef BACKLIGHTCONTROLS_H
#define BACKLIGHTCONTROLS_H
#include "../../pluginsManager/pluginsManager.h"
class backlightControls : public Plugin {
public:
backlightControls();
/**
* See src/pluginsManager/pluginsManager.h for available events
*/
void on_setup();
void on_track_change();
void on_stop_play();
};
#endif // BACKLIGHTCONTROLS_H

View File

@@ -1,3 +1,10 @@
/*
*******************************************************************************************
* Attention!
* This method of connecting plugins no longer works and is left here for history.
*******************************************************************************************
*/
/**************************************************************
Example of display backlight control depending on playback.

View File

@@ -0,0 +1,54 @@
/**
* Example of esp32 deep sleep when playback is stopped.
* To connect the plugin, copy its folder to the src/plugins directory.
*/
#include "deepsleep.h"
#include <Arduino.h>
#include <Ticker.h>
#include "../../core/options.h"
#include "../../core/display.h"
#define SLEEP_DELAY 60 /* 1 min deep sleep delay */
#define WAKEUP_PIN ENC_BTNB /* wakeup pin (one of: BTN_XXXX, ENC_BTNB, ENC2_BTNB) */
/* must be one of: 0,2,4,12,13,14,15,25,26,27,32,33,34,35,36,39 */
#define WAKEUP_LEVEL LOW /* wakeup level (usually LOW) */
Ticker deepSleepTicker;
deepSleep dsleep;
deepSleep::deepSleep() {
registerPlugin();
log_i("Plugin is registered");
}
void goToSleep(){
if(BRIGHTNESS_PIN!=255) analogWrite(BRIGHTNESS_PIN, 0); /* BRIGHTNESS_PIN added in v0.7.330 */
if(display.deepsleep()) { /* if deep sleep is possible */
esp_deep_sleep_start(); /* go to sleep */
}else{ /* else */
deepSleepTicker.detach(); /* detach the timer */
}
}
void deepSleep::on_setup(){ /* occurs during loading */
log_i("%s called", __func__ );
if(WAKEUP_PIN!=255){
esp_sleep_enable_ext0_wakeup((gpio_num_t)WAKEUP_PIN, WAKEUP_LEVEL); /* enable wakeup pin */
deepSleepTicker.attach(SLEEP_DELAY, goToSleep); /* attach to delay */
}
}
void deepSleep::on_start_play(){ /* occurs during player is start playing */
log_i("%s called", __func__ );
if(WAKEUP_PIN!=255){
deepSleepTicker.detach(); /* detach the timer */
}
}
void deepSleep::on_stop_play(){ /* occurs during player is stop playing */
log_i("%s called", __func__ );
if(WAKEUP_PIN!=255){
deepSleepTicker.attach(SLEEP_DELAY, goToSleep); /* attach to delay */
}
}

View File

@@ -0,0 +1,23 @@
/**
* Example of esp32 deep sleep when playback is stopped.
* To connect the plugin, copy its folder to the src/plugins directory.
*/
#ifndef DEEPSLEEP_H
#define DEEPSLEEP_H
#include "../../pluginsManager/pluginsManager.h"
class deepSleep : public Plugin {
public:
deepSleep();
/**
* See src/pluginsManager/pluginsManager.h for available events
*/
void on_setup();
void on_start_play();
void on_stop_play();
};
#endif // DEEPSLEEP_H

View File

@@ -1,3 +1,10 @@
/*
*******************************************************************************************
* Attention!
* This method of connecting plugins no longer works and is left here for history.
*******************************************************************************************
*/
/******************************************************************************************************************
Example of esp32 deep sleep when playback is stopped.

View File

@@ -0,0 +1,62 @@
/**
* Example of a plugin.
* To connect the plugin, copy its folder to the src/plugins directory.
*/
#include "helloworld.h"
#include "../../core/options.h"
helloWorld hellow;
helloWorld::helloWorld() {
registerPlugin();
log_i("Plugin is registered");
}
void helloWorld::on_setup(){
log_i("%s called", __func__ );
}
void helloWorld::on_end_setup(){
log_i("%s called", __func__ );
}
void helloWorld::on_connect(){
log_i("%s called", __func__ );
}
void helloWorld::on_start_play(){
log_i("%s called", __func__ );
}
void helloWorld::on_stop_play(){
log_i("%s called", __func__ );
}
void helloWorld::on_track_change(){
log_i("%s called", __func__ );
}
void helloWorld::on_station_change(){
log_i("%s called", __func__ );
}
void helloWorld::on_display_queue(requestParams_t &request, bool& result){
result = true;
log_i("%s called, type=%d, payload=%d ", __func__ , request.type, request.payload);
}
void helloWorld::on_display_player(){
log_i("%s called", __func__ );
}
void helloWorld::on_ticker(){
log_i("%s called", __func__ );
}
void helloWorld::on_btn_click(controlEvt_e &btnid){
log_i("%s called, btnid=%d", __func__ , btnid);
}

View File

@@ -0,0 +1,31 @@
/**
* Example of a plugin.
* To connect the plugin, copy its folder to the src/plugins directory.
*/
#ifndef HELLOWORLD_H
#define HELLOWORLD_H
#include "../../pluginsManager/pluginsManager.h"
class helloWorld : public Plugin {
public:
helloWorld();
/**
* See src/pluginsManager/pluginsManager.h for available events
*/
void on_setup();
void on_end_setup();
void on_connect();
void on_start_play();
void on_stop_play();
void on_track_change();
void on_station_change();
void on_display_queue(requestParams_t &request, bool& result);
void on_display_player();
void on_ticker();
void on_btn_click(controlEvt_e &btnid);
};
#endif // HELLOWORLD_H

View File

@@ -833,11 +833,7 @@ void AsyncWebSocketClient::binary(AsyncWebSocketMessageBuffer * buffer)
IPAddress AsyncWebSocketClient::remoteIP() {
if(!_client) {
#if ESP_IDF_VERSION_MAJOR < 5
return IPAddress(0U);
#else
return IPAddress(0ul);
#endif
return IPAddress((uint32_t)0);
}
return _client->remoteIP();
}

18
yoRadio/src/core/common.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef COMMON_H
#define COMMON_H
enum displayMode_e { PLAYER, VOL, STATIONS, NUMBERS, LOST, UPDATING, INFO, SETTINGS, TIMEZONE, WIFI, CLEAR, SLEEPING, SDCHANGE };
enum pages_e : uint8_t { PG_PLAYER=0, PG_DIALOG=1, PG_PLAYLIST=2 };
enum displayRequestType_e { BOOTSTRING, NEWMODE, CLOCK, NEWTITLE, NEWSTATION, NEXTSTATION, DRAWPLAYLIST, DRAWVOL, DBITRATE, AUDIOINFO, SHOWVUMETER, DSPRSSI, SHOWWEATHER, NEWWEATHER, PSTOP, PSTART, DSP_START, WAITFORSD, SDFILEINDEX, NEWIP, NOPE };
struct requestParams_t
{
displayRequestType_e type;
int payload;
};
enum controlEvt_e { EVT_NONE=255, EVT_BTNLEFT=0, EVT_BTNCENTER=1, EVT_BTNRIGHT=2, EVT_ENCBTNB=3, EVT_BTNUP=4, EVT_BTNDOWN=5, EVT_ENC2BTNB=6, EVT_BTNMODE=7 };
#endif

View File

@@ -745,9 +745,11 @@ void Config::doSleep(){
#ifdef USE_NEXTION
nextion.sleep();
#endif
#if !defined(ARDUINO_ESP32C3_DEV)
if(WAKE_PIN!=255) esp_sleep_enable_ext0_wakeup((gpio_num_t)WAKE_PIN, LOW);
esp_sleep_enable_timer_wakeup(config.sleepfor * 60 * 1000000ULL);
esp_deep_sleep_start();
#endif
}
void Config::doSleepW(){
@@ -756,8 +758,10 @@ void Config::doSleepW(){
#ifdef USE_NEXTION
nextion.sleep();
#endif
#if !defined(ARDUINO_ESP32C3_DEV)
if(WAKE_PIN!=255) esp_sleep_enable_ext0_wakeup((gpio_num_t)WAKE_PIN, LOW);
esp_deep_sleep_start();
#endif
}
void Config::sleepForAfter(uint16_t sf, uint16_t sa){

View File

@@ -7,6 +7,7 @@
//#include "SD.h"
#include "options.h"
#include "rtcsupport.h"
#include "../pluginsManager/pluginsManager.h"
#define EEPROM_SIZE 768
#define EEPROM_START 500

View File

@@ -204,10 +204,10 @@ void encoder2Loop() {
#if IR_PIN!=255
void irBlink() {
if(LED_BUILTIN==255) return;
if(REAL_LEDBUILTIN==255) return;
if (player.status() == STOPPED) {
for (uint8_t i = 0; i < 7; i++) {
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
digitalWrite(REAL_LEDBUILTIN, !digitalRead(REAL_LEDBUILTIN));
delay(100);
}
}
@@ -465,8 +465,10 @@ void controlsEvent(bool toRight, int8_t volDelta) {
void onBtnClick(int id) {
bool passBnCenter = (controlEvt_e)id==EVT_BTNCENTER || (controlEvt_e)id==EVT_ENCBTNB || (controlEvt_e)id==EVT_ENC2BTNB;
controlEvt_e btnid = static_cast<controlEvt_e>(id);
pm.on_btn_click(btnid);
if (network.status != CONNECTED && network.status!=SDREADY && (controlEvt_e)id!=EVT_BTNMODE && !passBnCenter) return;
switch ((controlEvt_e)id) {
switch (btnid) {
case EVT_BTNLEFT: {
controlsEvent(false);
break;

View File

@@ -1,13 +1,12 @@
#ifndef controls_h
#define controls_h
#include "options.h"
#include "common.h"
#if (ENC_BTNL!=255 && ENC_BTNR!=255) || (ENC2_BTNL!=255 && ENC2_BTNR!=255)
#include "../yoEncoder/yoEncoder.h"
#endif
enum controlEvt_e { EVT_BTNLEFT, EVT_BTNCENTER, EVT_BTNRIGHT, EVT_ENCBTNB, EVT_BTNUP, EVT_BTNDOWN, EVT_ENC2BTNB, EVT_BTNMODE };
//enum tsDirection_e { TSD_STAY, TSD_LEFT, TSD_RIGHT, TSD_UP, TSD_DOWN, TDS_REQUEST };
#if IR_PIN!=255

View File

@@ -240,6 +240,7 @@ void Display::_start() {
_station();
_time(false);
_bootStep = 2;
pm.on_display_player();
}
void Display::_showDialog(const char *title){
@@ -278,6 +279,7 @@ void Display::_swichMode(displayMode_e newmode) {
_meta.setText(config.station.name);
_nums.setText("");
_pager.setPage( pages[PG_PLAYER]);
pm.on_display_player();
}
if (newmode == VOL) {
#ifndef HIDE_IP
@@ -299,6 +301,7 @@ void Display::_swichMode(displayMode_e newmode) {
currentPlItem = config.store.lastStation;
_drawPlaylist();
}
}
void Display::resetQueue(){
@@ -368,6 +371,9 @@ void Display::loop() {
#endif
requestParams_t request;
if(xQueueReceive(displayQueue, &request, DSP_QUEUE_TICKS)){
bool pm_result;
pm.on_display_queue(request, pm_result);
if(pm_result)
switch (request.type){
case NEWMODE: _swichMode((displayMode_e)request.payload); break;
case CLOCK:
@@ -502,6 +508,7 @@ void Display::_title() {
if(_title2) _title2->setText("");
}
if (player_on_track_change) player_on_track_change();
pm.on_track_change();
}
void Display::_time(bool redraw) {

View File

@@ -5,19 +5,10 @@
#include "Arduino.h"
#include <Ticker.h>
#include "config.h"
#include "common.h"
#include "../displays/dspcore.h"
enum displayMode_e { PLAYER, VOL, STATIONS, NUMBERS, LOST, UPDATING, INFO, SETTINGS, TIMEZONE, WIFI, CLEAR, SLEEPING, SDCHANGE };
enum pages_e : uint8_t { PG_PLAYER=0, PG_DIALOG=1, PG_PLAYLIST=2 };
//enum dialogType_e : uint8_t { DG_NONE=0, DG_VOLUME=1, DG_LOST=2, DG_UPDATING=3, DG_NEXTION=4 };
enum displayRequestType_e { BOOTSTRING, NEWMODE, CLOCK, NEWTITLE, NEWSTATION, NEXTSTATION, DRAWPLAYLIST, DRAWVOL, DBITRATE, AUDIOINFO, SHOWVUMETER, DSPRSSI, SHOWWEATHER, NEWWEATHER, PSTOP, PSTART, DSP_START, WAITFORSD, SDFILEINDEX, NEWIP };
struct requestParams_t
{
displayRequestType_e type;
int payload;
};
#if NEXTION_RX!=255 && NEXTION_TX!=255
#define USE_NEXTION

View File

@@ -21,7 +21,7 @@ void doSync(void * pvParameters);
void ticks() {
if(!display.ready()) return; //waiting for SD is ready
pm.on_ticker();
static const uint16_t weatherSyncInterval=1800;
//static const uint16_t weatherSyncIntervalFail=10;
#if RTCSUPPORTED
@@ -121,7 +121,7 @@ bool MyNetwork::wifiBegin(bool silent){
while (WiFi.status() != WL_CONNECTED) {
if(!silent) Serial.print(".");
delay(500);
if(LED_BUILTIN!=255 && !silent) digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
if(REAL_LEDBUILTIN!=255 && !silent) digitalWrite(REAL_LEDBUILTIN, !digitalRead(REAL_LEDBUILTIN));
errcnt++;
if (errcnt > WIFI_ATTEMPTS) {
errcnt = 0;
@@ -182,7 +182,7 @@ void MyNetwork::begin() {
}
Serial.println("##[BOOT]#\tdone");
if(LED_BUILTIN!=255) digitalWrite(LED_BUILTIN, LOW);
if(REAL_LEDBUILTIN!=255) digitalWrite(REAL_LEDBUILTIN, LOW);
#if RTCSUPPORTED
rtc.getTime(&network.timeinfo);
@@ -191,6 +191,7 @@ void MyNetwork::begin() {
#endif
ctimer.attach(1, ticks);
if (network_on_connect) network_on_connect();
pm.on_connect();
}
void MyNetwork::setWifiParams(){

View File

@@ -1,7 +1,7 @@
#ifndef options_h
#define options_h
#define YOVERSION "0.9.342b"
#define YOVERSION "0.9.350"
/*******************************************************
DO NOT EDIT THIS FILE.
@@ -258,10 +258,24 @@ The connection tables are located here https://github.com/e2002/yoradio#connecti
#endif
/* ESP DEVBOARD */
#ifndef ARDUINO_ESP32S3_DEV
#if defined(ARDUINO_ESP32S3_DEV) || defined(ARDUINO_ESP32C3_DEV)
#define ESP_S3C3 1
#ifndef USE_BUILTIN_LED
#define USE_BUILTIN_LED true
#endif
#ifndef LED_BUILTIN_S3
#define LED_BUILTIN_S3 255
#endif
#if USE_BUILTIN_LED
#define REAL_LEDBUILTIN LED_BUILTIN
#else
#define REAL_LEDBUILTIN LED_BUILTIN_S3
#endif
#else
#ifndef LED_BUILTIN
#define LED_BUILTIN 255
#endif
#define REAL_LEDBUILTIN LED_BUILTIN
#endif
/* Other settings. You can overwrite them in the myoptions.h file */
#ifndef MUTE_PIN

View File

@@ -1,11 +1,11 @@
#ifndef optionschecker_h
#define optionschecker_h
#if LED_BUILTIN==TFT_RST
#if REAL_LEDBUILTIN==TFT_RST
# error LED_BUILTIN IS THE SAME AS TFT_RST. Check it in myoptions.h
#endif
#if LED_BUILTIN==VS1053_RST
#if REAL_LEDBUILTIN==VS1053_RST
# error LED_BUILTIN IS THE SAME AS VS1053_RST. Check it in myoptions.h
#endif
@@ -13,7 +13,7 @@
# error YOU MUST CHOOSE BETWEEN I2S DAC AND VS1053 BY DISABLING THE SECOND MODULE IN THE myoptions.h
#endif
#if !(defined(ARDUINO_ESP32_DEV) || defined(ARDUINO_ESP32S3_DEV))
#if !(defined(ARDUINO_ESP32_DEV) || defined(ARDUINO_ESP32S3_DEV) || defined(ARDUINO_ESP32C3_DEV))
# error ONLY MODULES "ESP32 Dev Module", "ESP32 Wrover Module" AND "ESP32 S3 Dev Module" ARE SUPPORTED. PLEASE SELECT ONE OF THEM IN THE MENU >> TOOLS >> BOARD
#endif

View File

@@ -109,6 +109,7 @@ void Player::_stop(bool alreadyStopped){
if(!alreadyStopped) stopSong();
if(!lockOutput) stopInfo();
if (player_on_stop_play) player_on_stop_play();
pm.on_stop_play();
}
void Player::initHeaders(const char *file) {
@@ -136,6 +137,7 @@ void Player::loop() {
}
_play((uint16_t)abs(requestP.payload));
if (player_on_station_change) player_on_station_change();
pm.on_station_change();
break;
}
case PR_VOL: {
@@ -168,7 +170,7 @@ void Player::loop() {
}
void Player::setOutputPins(bool isPlaying) {
if(LED_BUILTIN!=255) digitalWrite(LED_BUILTIN, LED_INVERT?!isPlaying:isPlaying);
if(REAL_LEDBUILTIN!=255) digitalWrite(REAL_LEDBUILTIN, LED_INVERT?!isPlaying:isPlaying);
bool _ml = MUTE_LOCK?!MUTE_VAL:(isPlaying?!MUTE_VAL:MUTE_VAL);
if(MUTE_PIN!=255) digitalWrite(MUTE_PIN, _ml);
}
@@ -215,6 +217,7 @@ void Player::_play(uint16_t stationId) {
setOutputPins(true);
display.putRequest(PSTART);
if (player_on_start_play) player_on_start_play();
pm.on_start_play();
}else{
telnet.printf("##ERROR#:\tError connecting to %s\n", config.station.url);
SET_PLAY_ERROR("Error connecting to %s", config.station.url);
@@ -239,6 +242,7 @@ void Player::browseUrl(){
setOutputPins(true);
display.putRequest(PSTART);
if (player_on_start_play) player_on_start_play();
pm.on_start_play();
}else{
telnet.printf("##ERROR#:\tError connecting to %s\n", burl);
SET_PLAY_ERROR("Error connecting to %s", burl);

View File

@@ -0,0 +1 @@
### Directory for placing your plugins.

View File

@@ -0,0 +1,84 @@
# Plugin Class
The `Plugin` class serves as a base class for creating plugins that hook into various system events.
To use it, inherit from `Plugin` and override the necessary virtual methods.
Examples of plugin usage can be found in the `examples/plugins` folder.
Place your new class in the `src/plugins/<MyPlugin>` directory
---
## Public Methods
### Constructor
`Plugin();`
Initializes the plugin when an instance is created.
---
### Destructor
`virtual ~Plugin();`
Cleans up resources when the plugin is destroyed.
---
## Virtual Methods (Override in derived classes)
### `on_setup()`
- **Description:** Called at the beginning of the sketch setup process.
- **Location:** `setup()`, `yoRadio.ino`.
### `on_end_setup()`
- **Description:** Called at the end of the sketch setup process.
- **Location:** `setup()`, `yoRadio.ino`.
### `on_connect()`
- **Description:** Triggered after a successful network connection.
- **Location:** `MyNetwork::begin()`, `yoRadio/src/core/network.cpp`.
### `on_start_play()`
- **Description:** Triggered when playback starts.
- **Location:**
- `Player::_play(uint16_t stationId)`, `yoRadio/src/core/player.cpp`.
- `Player::browseUrl()`, `yoRadio/src/core/player.cpp`.
### `on_stop_play()`
- **Description:** Triggered when playback stops.
- **Location:** `Player::_stop(bool alreadyStopped)`, `yoRadio/src/core/player.cpp`.
### `on_track_change()`
- **Description:** Triggered when the current track changes.
- **Location:** `Display::_title()`, `yoRadio/src/core/display.cpp`.
### `on_station_change()`
- **Description:** Triggered when the current station changes.
- **Location:** `Player::loop()`, `yoRadio/src/core/player.cpp`.
### `on_display_queue(requestParams_t &request, bool &result)`
- **Description:** Triggered when a command is dequeued for the display.
- **Parameters:**
- `request`: Reference to a `requestParams_t` structure (defined in `yoRadio/src/core/common.h`).
- `result`: Set to `false` to stop queue processing or `true` to continue.
- **Location:** `Display::loop()`, `yoRadio/src/core/display.cpp`.
### `on_display_player()`
- **Description:** Triggered when the player UI is displayed.
- **Location:**
- `Display::_start()`, `display.cpp`.
- `Display::_swichMode(displayMode_e newmode)`, `yoRadio/src/core/display.cpp`.
### `on_ticker()`
- **Description:** Triggered once every second.
- **Location:** `ticks()`, `yoRadio/src/core/network.cpp`.
### `on_btn_click(controlEvt_e &btnid)`
- **Description:** Triggered when a button is clicked.
- **Parameters:**
- `btnid`: Reference to the button ID (defined in `yoRadio/src/core/common.h`).
- **Location:** `onBtnClick(int id)`, `yoRadio/src/core/controls.cpp`.
---
## Protected Methods
### `registerPlugin()`
- **Description:** Registers the plugin with the plugin manager.

View File

@@ -0,0 +1,26 @@
#include "pluginsManager.h"
pluginsManager pm;
Plugin::Plugin() {
}
void Plugin::registerPlugin() {
pm.add(this);
}
void pluginsManager::add(Plugin* plugin) {
plugins.push_back(plugin);
}
size_t pluginsManager::count() const {
return plugins.size();
}
Plugin* pluginsManager::get(size_t index) {
if (index < plugins.size()) {
return plugins[index];
}
return nullptr;
}

View File

@@ -0,0 +1,149 @@
#ifndef PLUGINSMANAGER_H
#define PLUGINSMANAGER_H
#include <Arduino.h>
#include <vector>
#include <functional>
#include "../core/common.h"
class pluginsManager;
/**
* Plugin Class
*
* Base class for creating plugins that hook into various system events.
* To use it, inherit from Plugin and override the necessary virtual methods.
* Examples of plugin usage can be found in the `examples/plugins` folder.
* Place your new class in the src/plugins/<MyPlugin> directory
*/
class Plugin {
public:
/**
* Constructor
* Initializes the plugin when an instance is created.
*/
Plugin();
/**
* Destructor
* Cleans up resources when the plugin is destroyed.
*/
virtual ~Plugin() {}
// Virtual Methods (Override in derived classes):
/**
* Called at the beginning of the sketch setup process.
* Location: setup(), yoRadio.ino
*/
virtual void on_setup() __attribute__((weak)) {}
/**
* Called at the end of the sketch setup process.
* Location: setup(), yoRadio.ino
*/
virtual void on_end_setup() __attribute__((weak)) {}
/**
* Triggered after a successful network connection.
* Location: MyNetwork::begin(), yoRadio/src/core/network.cpp
*/
virtual void on_connect() __attribute__((weak)) {}
/**
* Triggered when playback starts.
* Location:
* - Player::_play(uint16_t stationId), yoRadio/src/core/player.cpp
* - Player::browseUrl(), yoRadio/src/core/player.cpp
*/
virtual void on_start_play() __attribute__((weak)) {}
/**
* Triggered when playback stops.
* Location: Player::_stop(bool alreadyStopped), yoRadio/src/core/player.cpp
*/
virtual void on_stop_play() __attribute__((weak)) {}
/**
* Triggered when the current track changes.
* Location: Display::_title(), yoRadio/src/core/display.cpp
*/
virtual void on_track_change() __attribute__((weak)) {}
/**
* Triggered when the current station changes.
* Location: Player::loop(), yoRadio/src/core/player.cpp
*/
virtual void on_station_change() __attribute__((weak)) {}
/**
* Triggered when a command is dequeued for the display.
* Parameters:
* - request: Reference to a requestParams_t structure (defined in yoRadio/src/core/common.h).
* - result: Set to `false` to stop queue processing or `true` to continue.
* Location: Display::loop(), yoRadio/src/core/display.cpp
*/
virtual void on_display_queue(requestParams_t &request, bool &result) __attribute__((weak)) {}
/**
* Triggered when the player UI is displayed.
* Location:
* - Display::_start(), yoRadio/src/core/display.cpp
* - Display::_swichMode(displayMode_e newmode), yoRadio/src/core/display.cpp
*/
virtual void on_display_player() __attribute__((weak)) {}
/**
* Triggered once every second.
* Location: ticks(), yoRadio/src/core/network.cpp
*/
virtual void on_ticker() __attribute__((weak)) {}
/**
* Triggered when a button is clicked.
* Parameters:
* - btnid: Reference to the button ID (defined in yoRadio/src/core/common.h).
* Location: onBtnClick(int id), yoRadio/src/core/controls.cpp
*/
virtual void on_btn_click(controlEvt_e &btnid) __attribute__((weak)) {}
protected:
/**
* Registers the plugin with the plugin manager.
*/
void registerPlugin();
};
class pluginsManager {
public:
void add(Plugin* plugin);
size_t count() const;
Plugin* get(size_t index);
requestParams_t *request;
template <typename Func, typename... Args>
void call_event(Func&& func, Args&&... args){
for (auto* plugin : plugins) {
if (plugin) {
(plugin->*func)(std::forward<Args>(args)...);
}
}
}
void on_setup(){ call_event(&Plugin::on_setup); }
void on_end_setup(){ call_event(&Plugin::on_end_setup); }
void on_connect(){ call_event(&Plugin::on_connect); }
void on_start_play(){ call_event(&Plugin::on_start_play); }
void on_stop_play(){ call_event(&Plugin::on_stop_play); }
void on_track_change(){ call_event(&Plugin::on_track_change); }
void on_station_change(){ call_event(&Plugin::on_station_change); }
void on_display_queue(requestParams_t &request, bool& result){ call_event(&Plugin::on_display_queue, request, result); }
void on_display_player(){ call_event(&Plugin::on_display_player); }
void on_ticker(){ call_event(&Plugin::on_ticker); }
void on_btn_click(controlEvt_e &btnid){ call_event(&Plugin::on_btn_click, btnid); }
private:
std::vector<Plugin*> plugins;
};
extern pluginsManager pm;
#endif // PLUGINSMANAGER_H

View File

@@ -31,8 +31,9 @@ extern __attribute__((weak)) void yoradio_on_setup();
void setup() {
Serial.begin(115200);
if(LED_BUILTIN!=255) pinMode(LED_BUILTIN, OUTPUT);
if(REAL_LEDBUILTIN!=255) pinMode(REAL_LEDBUILTIN, OUTPUT);
if (yoradio_on_setup) yoradio_on_setup();
pm.on_setup();
config.init();
display.init();
player.init();
@@ -60,6 +61,7 @@ void setup() {
if (config.getMode()==PM_SDCARD) player.initHeaders(config.station.url);
player.lockOutput=false;
if (config.store.smartstart == 1) player.sendCommand({PR_PLAY, config.store.lastStation});
pm.on_end_setup();
}
void loop() {