Files
TTGO_TWatch_Library/examples/LVGL/SimplePlayer/SimplePlayer.ino
2020-07-13 15:37:29 +08:00

265 lines
6.8 KiB
C++

#pragma mark - Depend ESP8266Audio and ESP8266_Spiram libraries
/*
cd ~/Arduino/libraries
git clone https://github.com/earlephilhower/ESP8266Audio
git clone https://github.com/Gianbacchio/ESP8266_Spiram
*/
#include "config.h"
#include <WiFi.h>
#include <HTTPClient.h> //Remove Audio Lib error
#include "AudioFileSourceSD.h"
#include "AudioFileSourceID3.h"
#include "AudioGeneratorMP3.h"
#include "AudioOutputI2S.h"
#include <Esp.h>
Ticker tk;
TTGOClass *ttgo;
AudioGeneratorMP3 *mp3;
AudioFileSourceSD *file;
AudioOutputI2S *out;
AudioFileSourceID3 *id3;
static lv_obj_t *list_cont;
static lv_obj_t *play_cont;
static lv_obj_t *curr_list;
static lv_obj_t *label;
static lv_obj_t *scr;
static lv_obj_t *list;
static lv_obj_t *img_btn[3];
static lv_obj_t *button[3];
static const void *src_img_btn[4] = {LV_SYMBOL_PREV, LV_SYMBOL_PAUSE, LV_SYMBOL_NEXT, LV_SYMBOL_PLAY};
static void list_event_handler(lv_obj_t *obj, lv_event_t event);
static char filename[128];
uint8_t state = 255;
LV_IMG_DECLARE(bg1);
enum {
PLAY,
PAUSE,
NEXT,
PREV,
};
void create_gui();
void pressed()
{
ESP.restart();
}
static void list_event_handler(lv_obj_t *obj, lv_event_t event)
{
if (event == LV_EVENT_CLICKED) {
curr_list = obj;
const char *txt = lv_list_get_btn_text(obj);
Serial.printf("Clicked %s\n", txt);
state = PLAY;
strcpy(filename, txt);
create_gui();
file->open(txt);
mp3->begin(id3, out);
}
}
static void event_handler(lv_obj_t *obj, lv_event_t event)
{
if (event == LV_EVENT_CLICKED) {
if (button[0] == obj) {
if (state != PLAY)return;
lv_obj_t *prev_btn = lv_list_get_prev_btn(list, curr_list);
if (prev_btn == NULL) {
Serial.println("prev is null");
return;
}
curr_list = prev_btn;
const char *txt = lv_list_get_btn_text(prev_btn);
lv_label_set_text(label, txt);
out->stop();
if (mp3->isRunning())
mp3->stop();
file->open(txt);
mp3->begin(id3, out);
} else if (button[1] == obj) {
if (state == PAUSE) {
state = PLAY;
lv_img_set_src(img_btn[1], LV_SYMBOL_PAUSE);
out->begin();
} else {
state = PAUSE;
out->stop();
lv_img_set_src(img_btn[1], LV_SYMBOL_PLAY);
}
} else if (button[2] == obj) {
if (state != PLAY)return;
lv_obj_t *next_btn = lv_list_get_next_btn(list, curr_list);
if (next_btn == NULL) {
Serial.println("next is null");
return;
}
curr_list = next_btn;
const char *txt = lv_list_get_btn_text(next_btn);
lv_label_set_text(label, txt);
out->stop();
if (mp3->isRunning())
mp3->stop();
file->open(txt);
mp3->begin(id3, out);
}
}
}
void create_gui()
{
lv_obj_set_hidden(list_cont, true);
play_cont = lv_cont_create(scr, NULL);
lv_obj_set_size(play_cont, 240, 240);
lv_obj_t *img = lv_img_create(play_cont, NULL);
lv_img_set_src(img, &bg1);
lv_obj_align(img, NULL, LV_ALIGN_CENTER, 0, 0);
label = lv_label_create(play_cont, NULL);
lv_label_set_text(label, filename);
lv_label_set_long_mode(label, LV_LABEL_LONG_SROLL);
lv_obj_set_width(label, 80);
lv_obj_align(label, play_cont, LV_ALIGN_IN_TOP_MID, 0, 50);
for (uint8_t i = 0; i < 3; i++) {
button[i] = lv_btn_create(play_cont, NULL);
lv_obj_set_size(button[i], 50, 50);
img_btn[i] = lv_img_create(button[i], NULL);
lv_img_set_src(img_btn[i], src_img_btn[i]);
lv_obj_set_event_cb(button[i], event_handler);
}
lv_obj_align(button[0], NULL, LV_ALIGN_IN_LEFT_MID, 40, 40);
for (uint8_t i = 1; i < 3; i++) {
lv_obj_align(button[i], button[i - 1], LV_ALIGN_OUT_RIGHT_MID, 10, 0);
}
}
int searchMusic(fs::FS &fs, const char *dirname, uint8_t levels)
{
int searchFiles = 0;
File root = fs.open(dirname);
if (!root) {
Serial.println("- failed to open directory");
return 0;
}
if (!root.isDirectory()) {
Serial.println(" - not a directory");
return 0;
}
File file = root.openNextFile();
while (file) {
if (!file.isDirectory()) {
String name = String(file.name());
if (name.endsWith(".mp3") || name.endsWith(".MP3")) {
if (searchFiles++ > 50)return searchFiles;
lv_obj_t *list_btn = lv_list_add_btn(list, LV_SYMBOL_FILE, file.name());
lv_obj_set_event_cb(list_btn, list_event_handler);
}
}
file = root.openNextFile();
}
return searchFiles;
}
void setup()
{
WiFi.mode(WIFI_OFF);
delay(500);
Serial.begin(115200);
ttgo = TTGOClass::getWatch();
ttgo->begin();
ttgo->openBL();
ttgo->tft->fillScreen(TFT_BLACK);
ttgo->tft->setTextFont(2);
ttgo->tft->setCursor(0, 0);
ttgo->tft->fillScreen(TFT_BLACK);
ttgo->tft->println("Sample MP3 playback begins");
ttgo->button->setPressedHandler(pressed);
tk.attach_ms(30, []() {
ttgo->button->loop();
});
//!Turn on the audio power
ttgo->enableLDO3();
file = new AudioFileSourceSD();
id3 = new AudioFileSourceID3(file);
out = new AudioOutputI2S();
//! External DAC decoding
out->SetPinout(TWATCH_DAC_IIS_BCK, TWATCH_DAC_IIS_WS, TWATCH_DAC_IIS_DOUT);
mp3 = new AudioGeneratorMP3();
while (1) {
if (ttgo->sdcard_begin()) {
Serial.println("sd begin pass");
break;
}
Serial.println("sd begin fail,wait 1 sec");
delay(1000);
}
ttgo->lvgl_begin();
scr = lv_scr_act();
list_cont = lv_cont_create(scr, NULL);
lv_obj_set_size(list_cont, 240, 240);
list = lv_list_create(list_cont, NULL);
lv_obj_set_size(list, 240, 240);
lv_obj_align(list, list_cont, LV_ALIGN_CENTER, 0, 0);
if (searchMusic(SD, "/", 2) == 0) {
Serial.println("No Search mp3 file");
while (1) {
delay(1000);
}
}
}
void loop()
{
switch (state) {
case PLAY:
if (mp3->isRunning()) {
if (!mp3->loop()) {
mp3->stop();
state = 255;
}
}
break;
case PAUSE:
break;
case NEXT:
break;
case PREV:
break;
default:
delay(5);
break;
}
lv_task_handler();
}