//
// NB! This is a file generated from the .4Dino file, changes will be lost
//     the next time the .4Dino file is built
//
/*************************************************************************************************/
/*                                                                                               */
/*  Internet Radio Demo - 4D Systems ESP32-P4 (7", 8", 9" or 10.1") + ESP32-P4-C6-WiFi Hardware  */
/*  Configure your SSID and Password, and then load into ESP32-P4 module using WS4               */
/*                                                                                               */
/*  Tested with ESP32 Arduino Core 3.3.7 (ESP-IDF 5.5.2) & ESP-Hosted 2.11.7                     */
/*                                                                                               */
/*  Dependant on ESP32-audioI2S-master library by schreibfaul1 (3.4.4 Tested)                    */
/*                                                                                               */
/*  Demo uses Radio Stations URL's for New Zealand Stations - Change as you see fit              */
/*                                                                                               */
/*************************************************************************************************/

#include "gfx4desp32_ESP32_P4_70CT.h"

gfx4desp32_ESP32_P4_70CT gfx = gfx4desp32_ESP32_P4_70CT();

#include "InternetRadioConst.h"    // Note. This file will not be created if there are no generated graphics

// Uncomment if using GC* in program flash.
#include "InternetRadioGCx.h"     // Note. This file will be generated when graphics destination program flash

#include "Arduino.h"
#include "Audio.h"     //ESP32-audioI2S Library
#include "WiFi.h"
#include "es8311.h"    //ES8311 library files in project folder
#include "Wire.h"
#include "esp_hosted.h"

Audio audio;
ES8311 es;

String ssid =     "SSID";              // EDIT THIS
String password = "PASSWORD";          // EDIT THIS

int Volume = 60;
int lastVolume = 60;
bool Play = false;
bool lastPlay = false;
String Station;
String StationName;
bool ReconnectWiFi = false;
int Brightness = 15;
int lastBrightness = 15;

int vucount;
bool vuready;
int vulev[2890];

void setup()
{
  gfx.begin();
  gfx.Cls(WHITE);
  gfx.ScrollEnable(false);
  gfx.BacklightOn(true);
  gfx.Orientation(LANDSCAPE_R);
  gfx.SmoothScrollSpeed(5);
  gfx.TextColor(BLACK, WHITE); gfx.Font(2);  gfx.TextSize(1);
// Uncomment one of the three followin statements depending on the type of graphics file you are using GCI, GCJ, or GC* in program flash.
//gfx.Open4dGFX("InternetRadio"); // Opens DAT and GCI files for read using filename without extension.
//gfx.Open4dGFX("InternetRadio.gcj"); // Opens GCJ file for read using complete filename.
  gfx.Open4dGFX(InternetRadio, InternetRadio_size); // Opens GCJ from program space using array name and size
//gfx.Open4dGFX(InternetRadio_dat, ESP32-P4-InternetRadio_dat_size, ESP32-P4-InternetRadio_gci, ESP32-P4-InternetRadio_gci_size); // Opens DAT/GCI from program space using array name and size
  gfx.touch_Set(TOUCH_ENABLE);                // Global touch enabled

  // Form Background
  gfx.UserImage(iForm1) ;  // Form1

  // Volume Slider
  gfx.imageTouchEnable(iSlider1, true) ;                     // init_Slider1 enable touch of widget (on Form1)
  gfx.UserImages(iSlider1, 10) ;                             // init_Slider1 show initially, if required (on Form1) 50 is bottom, 10 is at 60 position

  // Brightness Slider
  gfx.imageTouchEnable(iSlider2, true) ;                     // init_Slider2 enable touch of widget (on Form1)
  gfx.UserImages(iSlider2, Brightness-1) ;                   // init_Slider2 show initially as Brightness value

  // Play / Stop / Reconnect Wifi Buttons
  gfx.imageTouchEnable(iUserbutton1, true, MOMENTARY) ;      // init_Userbutton1 enable touch of widget (on Form1)
  gfx.UserImages(iUserbutton1,0) ;                           // init_Userbutton1 show initially, if required (on Form1)
  gfx.imageTouchEnable(iUserbutton2, true, MOMENTARY) ;      // init_Userbutton2 enable touch of widget (on Form1)
  gfx.UserImages(iUserbutton2,0) ;                           // init_Userbutton2 show initially, if required (on Form1)
  gfx.imageTouchEnable(iUserbutton3, true, MOMENTARY) ;      // init_Userbutton3 enable touch of widget (on Form1)
  gfx.UserImages(iUserbutton3,0) ;                           // init_Userbutton3 show initially, if required (on Form1)

  // Station Buttons
  gfx.imageTouchEnable(i4Dbutton1, true, TOGGLE4STATES) ;    // init_4Dbutton1 enable touch of widget (on Form1)
  gfx.UserImages(i4Dbutton1,0) ;                             // init_4Dbutton1 show initially, if required (on Form1)
  gfx.imageTouchEnable(i4Dbutton2, true, TOGGLE4STATES) ;    // init_4Dbutton2 enable touch of widget (on Form1)
  gfx.UserImages(i4Dbutton2,0) ;                             // init_4Dbutton2 show initially, if required (on Form1)
  gfx.imageTouchEnable(i4Dbutton3, true, TOGGLE4STATES) ;    // init_4Dbutton3 enable touch of widget (on Form1)
  gfx.UserImages(i4Dbutton3,0) ;                             // init_4Dbutton3 show initially, if required (on Form1)
  gfx.imageTouchEnable(i4Dbutton4, true, TOGGLE4STATES) ;    // init_4Dbutton4 enable touch of widget (on Form1)
  gfx.UserImages(i4Dbutton4,0) ;                             // init_4Dbutton4 show initially, if required (on Form1)
  gfx.imageTouchEnable(i4Dbutton5, true, TOGGLE4STATES) ;    // init_4Dbutton5 enable touch of widget (on Form1)
  gfx.UserImages(i4Dbutton5,0) ;                             // init_4Dbutton5 show initially, if required (on Form1)
  gfx.imageTouchEnable(i4Dbutton10, true, TOGGLE4STATES) ;   // init_4Dbutton10 enable touch of widget (on Form1)
  gfx.UserImages(i4Dbutton10,0) ;                            // init_4Dbutton10 show initially, if required (on Form1)
  gfx.imageTouchEnable(i4Dbutton6, true, TOGGLE4STATES) ;    // init_4Dbutton6 enable touch of widget (on Form1)
  gfx.UserImages(i4Dbutton6,0) ;                             // init_4Dbutton6 show initially, if required (on Form1)
  gfx.imageTouchEnable(i4Dbutton7, true, TOGGLE4STATES) ;    // init_4Dbutton7 enable touch of widget (on Form1)
  gfx.UserImages(i4Dbutton7,0) ;                             // init_4Dbutton7 show initially, if required (on Form1)
  gfx.imageTouchEnable(i4Dbutton8, true, TOGGLE4STATES) ;    // init_4Dbutton8 enable touch of widget (on Form1)
  gfx.UserImages(i4Dbutton8,0) ;                             // init_4Dbutton8 show initially, if required (on Form1)
  gfx.imageTouchEnable(i4Dbutton9, true, TOGGLE4STATES) ;    // init_4Dbutton9 enable touch of widget (on Form1)
  gfx.UserImages(i4Dbutton9,0) ;                             // init_4Dbutton9 show initially, if required (on Form1)

  // Text & Images
  gfx.UserImage(iStatictext14) ;  // STATUS
  gfx.UserImage(iStatictext7) ;  // VOLUME
  gfx.UserImage(iStatictext8) ;  // CONTROLS
  gfx.UserImage(iStatictext16) ;  // BRIGHTNESS

  gfx.UserImage(iStatictext1) ;  // STATIONS
  gfx.UserImage(iStatictext2) ;  // Brian FM
  gfx.UserImage(iStatictext3) ;  // Radio Hauraki
  gfx.UserImage(iStatictext4) ;  // The Rock
  gfx.UserImage(iStatictext5) ;  // Magic
  gfx.UserImage(iStatictext6) ;  // Newstalk ZB
  gfx.UserImage(iStatictext9) ;  // The Sound
  gfx.UserImage(iStatictext10) ;  // The Generator FM
  gfx.UserImage(iStatictext11) ;  // Dave FM
  gfx.UserImage(iStatictext12) ;  // Metal Radio
  gfx.UserImage(iStatictext13) ;  // The Edge

  gfx.UserImage(iImage1) ;  // 4D Systems
  gfx.UserImage(iStatictext15) ;  // Internet Radio Demo

  gfx.UserImage(iImage2) ;  // VU Boarder

  // Status Window
  gfx.TextWindow(35, 65, 415, 355, NAVY, WHITE);
  gfx.TWprintln("----------------------------------");
  //gfx.TWprint("ESP32 Chip: %s\n", ESP.getChipModel());
  gfx.TWprint("ESP32 Chip: "); gfx.TWprintln(ESP.getChipModel());
  //gfx.TWprint("Arduino Version: %d.%d.%d\n", ESP_ARDUINO_VERSION_MAJOR, ESP_ARDUINO_VERSION_MINOR, ESP_ARDUINO_VERSION_PATCH);
  gfx.TWprint("Arduino Version: "); gfx.TWprint(String(ESP_ARDUINO_VERSION_MAJOR)); gfx.TWprint("."); gfx.TWprint(String(ESP_ARDUINO_VERSION_MINOR)); gfx.TWprint("."); gfx.TWprintln(String(ESP_ARDUINO_VERSION_PATCH));
  //gfx.TWprint("ESP-IDF Version: %d.%d.%d\n", ESP_IDF_VERSION_MAJOR, ESP_IDF_VERSION_MINOR, ESP_IDF_VERSION_PATCH);
  gfx.TWprint("ESP-IDF Version: "); gfx.TWprint(String(ESP_IDF_VERSION_MAJOR)); gfx.TWprint("."); gfx.TWprint(String(ESP_IDF_VERSION_MINOR)); gfx.TWprint("."); gfx.TWprintln(String(ESP_IDF_VERSION_PATCH));

  WiFi.setPins(18, 19, 14, 15, 16, 17, 3);
  WiFi.begin(ssid.c_str(), password.c_str());

  esp_hosted_coprocessor_fwver_t version;
  if (esp_hosted_get_coprocessor_fwversion(&version) == ESP_OK)
  {
    gfx.TWprint("ESP Hosted Co. FW Version: ");
    gfx.TWprint(version.major1); gfx.TWprint("."); gfx.TWprint(version.minor1); gfx.TWprint("."); gfx.TWprintln(version.patch1);
  }
  else
  {
    gfx.TWprintln("Failed to get Hosted Co. FW version\n");
  }
  gfx.TWprintln("----------------------------------\n");

  gfx.TWprint("Connecting to "); gfx.TWprint(ssid);
  while (WiFi.status() != WL_CONNECTED)
  {
    delay(1500);
    gfx.TWprint(".");
  }
  gfx.TWprintln("\nWiFi Connected");

  audio.setPinout(I2S_SCLK, I2S_LRCK, I2S_DSDIN, I2S_MCLK);
  audio.setVolume(21); // default 0...21 (MP3 Volume)

  pinMode(AMP_CTRL, OUTPUT);
  digitalWrite(AMP_CTRL, LOW); // Disable Amplifier to start with

  if (!es.begin(I2C_SDA, I2C_SCL, 400000)) log_e("ES8311 begin failed");
  es.setVolume(Volume);  // Codec Volume
  es.setBitsPerSample(16);

  Audio::audio_info_callback = my_audio_info;

} // end Setup **do not alter, remove or duplicate this line**

void loop()
{
  // put your main code here, to run repeatedly:
  int itouched, val ;
  if (gfx.touch_Update())
  {
    itouched = gfx.imageTouched() ;
    switch (itouched)
    {                                                         // start touched selection **do not alter, remove or duplicate this line**
      // case statements for Knobs and Sliders go here
      case iSlider1 :                                      // process_Slider1 process (Volume Slider)
        Volume = 50 + gfx.imageAutoSlider(iSlider1, VERTICAL_SLIDER, gfx.touch_GetY(), 8, 8);
        break ;
      case iSlider2 :                                      // process_Slider2 process (Brightness Slider). Add 1 so brightness 0-14 is actually 1-15
        Brightness = gfx.imageAutoSlider(iSlider2, HORIZONTAL_SLIDER, gfx.touch_GetX(), 8, 8) + 1;
        break ;
      default :                                               // end touched selection **do not alter, remove or duplicate this line**
        int button = gfx.ImageTouchedAuto();    // use default for keyboards and buttons
        val = gfx.getImageValue(button);

        switch (button)
        {                                                     // start button selection **do not alter, remove or duplicate this line**
          // case, one for each button or keyboard, default should end up as -1
          case iUserbutton1 :                                      // process_Userbutton1 process Button (Play button)
            Play = true;
            break ;
          case iUserbutton2 :                                      // process_Userbutton2 process Button (Stop button)
            Play = false;
            break ;
          case iUserbutton3 :                                      // process_Userbutton3 process Button (Reconnect WiFi button)
            ReconnectWiFi = true;
            break ;
          case i4Dbutton1 :                                      // process_4Dbutton1 process Button (Station #1)
            Station = "https://ais-sa1.streamon.fm/7100_128k.aac";
            StationName = "Brian FM";
            gfx.TWprint(StationName); gfx.TWprintln(" Station Selected");
            gfx.UserImages(i4Dbutton1, 2);
            gfx.UserImages(i4Dbutton2, 0);
            gfx.UserImages(i4Dbutton3, 0);
            gfx.UserImages(i4Dbutton4, 0);
            gfx.UserImages(i4Dbutton5, 0);
            gfx.UserImages(i4Dbutton6, 0);
            gfx.UserImages(i4Dbutton7, 0);
            gfx.UserImages(i4Dbutton8, 0);
            gfx.UserImages(i4Dbutton9, 0);
            gfx.UserImages(i4Dbutton10, 0);
            audio.stopSong();
            Play = false;
            break ;
          case i4Dbutton2 :                                      // process_4Dbutton2 process Button (Station #2)
            Station = "http://playerservices.streamtheworld.com/api/livestream-redirect/NZME_14AAC.m3u8";
            StationName = "Radio Hauraki";
            gfx.TWprint(StationName); gfx.TWprintln(" Station Selected");
            gfx.UserImages(i4Dbutton1, 0);
            gfx.UserImages(i4Dbutton2, 2);
            gfx.UserImages(i4Dbutton3, 0);
            gfx.UserImages(i4Dbutton4, 0);
            gfx.UserImages(i4Dbutton5, 0);
            gfx.UserImages(i4Dbutton6, 0);
            gfx.UserImages(i4Dbutton7, 0);
            gfx.UserImages(i4Dbutton8, 0);
            gfx.UserImages(i4Dbutton9, 0);
            gfx.UserImages(i4Dbutton10, 0);
            audio.stopSong();
            Play = false;
            break ;
          case i4Dbutton3 :                                      // process_4Dbutton3 process Button (Station #3)
            Station = "https://digitalstreams.mediaworks.nz/rock_net/playlist.m3u8";
            StationName = "The Rock FM";
            gfx.TWprint(StationName); gfx.TWprintln(" Station Selected");
            gfx.UserImages(i4Dbutton1, 0);
            gfx.UserImages(i4Dbutton2, 0);
            gfx.UserImages(i4Dbutton3, 2);
            gfx.UserImages(i4Dbutton4, 0);
            gfx.UserImages(i4Dbutton5, 0);
            gfx.UserImages(i4Dbutton6, 0);
            gfx.UserImages(i4Dbutton7, 0);
            gfx.UserImages(i4Dbutton8, 0);
            gfx.UserImages(i4Dbutton9, 0);
            gfx.UserImages(i4Dbutton10, 0);
            audio.stopSong();
            Play = false;
            break ;
          case i4Dbutton4 :                                      // process_4Dbutton4 process Button (Station #4)
            Station = "https://digitalstreams.mediaworks.nz/mmusic_net/playlist.m3u8";
            StationName = "Magic FM";
            gfx.TWprint(StationName); gfx.TWprintln(" Station Selected");
            gfx.UserImages(i4Dbutton1, 0);
            gfx.UserImages(i4Dbutton2, 0);
            gfx.UserImages(i4Dbutton3, 0);
            gfx.UserImages(i4Dbutton4, 2);
            gfx.UserImages(i4Dbutton5, 0);
            gfx.UserImages(i4Dbutton6, 0);
            gfx.UserImages(i4Dbutton7, 0);
            gfx.UserImages(i4Dbutton8, 0);
            gfx.UserImages(i4Dbutton9, 0);
            gfx.UserImages(i4Dbutton10, 0);
            audio.stopSong();
            Play = false;
            break ;
          case i4Dbutton5 :                                      // process_4Dbutton5 process Button (Station #5)
            Station = "http://streaming.radiomyway.co.nz/zbwnalt.pls";
            StationName = "Newstalk ZB";
            gfx.TWprint(StationName); gfx.TWprintln(" Station Selected");
            gfx.UserImages(i4Dbutton1, 0);
            gfx.UserImages(i4Dbutton2, 0);
            gfx.UserImages(i4Dbutton3, 0);
            gfx.UserImages(i4Dbutton4, 0);
            gfx.UserImages(i4Dbutton5, 2);
            gfx.UserImages(i4Dbutton6, 0);
            gfx.UserImages(i4Dbutton7, 0);
            gfx.UserImages(i4Dbutton8, 0);
            gfx.UserImages(i4Dbutton9, 0);
            gfx.UserImages(i4Dbutton10, 0);
            audio.stopSong();
            Play = false;
            break ;
          case i4Dbutton10 :                                      // process_4Dbutton10 process Button (Station #6)
            Station = "https://digitalstreams.mediaworks.nz/sound_net/playlist.m3u8";
            StationName = "The Sound";
            gfx.TWprint(StationName); gfx.TWprintln(" Station Selected");
            gfx.UserImages(i4Dbutton1, 0);
            gfx.UserImages(i4Dbutton2, 0);
            gfx.UserImages(i4Dbutton3, 0);
            gfx.UserImages(i4Dbutton4, 0);
            gfx.UserImages(i4Dbutton5, 0);
            gfx.UserImages(i4Dbutton6, 0);
            gfx.UserImages(i4Dbutton7, 0);
            gfx.UserImages(i4Dbutton8, 0);
            gfx.UserImages(i4Dbutton9, 0);
            gfx.UserImages(i4Dbutton10, 2);
            audio.stopSong();
            Play = false;
            break ;
          case i4Dbutton6 :                                      // process_4Dbutton6 process Button (Station #7)
            Station = "https://s1.myradiostream.com/14268/stream/1/";
            StationName = "The Generator FM";
            gfx.TWprint(StationName); gfx.TWprintln(" Station Selected");
            gfx.UserImages(i4Dbutton1, 0);
            gfx.UserImages(i4Dbutton2, 0);
            gfx.UserImages(i4Dbutton3, 0);
            gfx.UserImages(i4Dbutton4, 0);
            gfx.UserImages(i4Dbutton5, 0);
            gfx.UserImages(i4Dbutton6, 2);
            gfx.UserImages(i4Dbutton7, 0);
            gfx.UserImages(i4Dbutton8, 0);
            gfx.UserImages(i4Dbutton9, 0);
            gfx.UserImages(i4Dbutton10, 0);
            audio.stopSong();
            Play = false;
            break ;
          case i4Dbutton7 :                                      // process_4Dbutton7 process Button (Station #8)
            Station = "http://davefmradio.no-ip.org:8000/stream";
            StationName = "Dave FM";
            gfx.TWprint(StationName); gfx.TWprintln(" Station Selected");
            gfx.UserImages(i4Dbutton1, 0);
            gfx.UserImages(i4Dbutton2, 0);
            gfx.UserImages(i4Dbutton3, 0);
            gfx.UserImages(i4Dbutton4, 0);
            gfx.UserImages(i4Dbutton5, 0);
            gfx.UserImages(i4Dbutton6, 0);
            gfx.UserImages(i4Dbutton7, 2);
            gfx.UserImages(i4Dbutton8, 0);
            gfx.UserImages(i4Dbutton9, 0);
            gfx.UserImages(i4Dbutton10, 0);
            audio.stopSong();
            Play = false;
            break ;
          case i4Dbutton8 :                                      // process_4Dbutton8 process Button (Station #9)
            Station = "http://curiosity.shoutca.st:9073/stream";
            StationName = "Metal Radio";
            gfx.TWprint(StationName); gfx.TWprintln(" Station Selected");
            gfx.UserImages(i4Dbutton1, 0);
            gfx.UserImages(i4Dbutton2, 0);
            gfx.UserImages(i4Dbutton3, 0);
            gfx.UserImages(i4Dbutton4, 0);
            gfx.UserImages(i4Dbutton5, 0);
            gfx.UserImages(i4Dbutton6, 0);
            gfx.UserImages(i4Dbutton7, 0);
            gfx.UserImages(i4Dbutton8, 2);
            gfx.UserImages(i4Dbutton9, 0);
            gfx.UserImages(i4Dbutton10, 0);
            audio.stopSong();
            Play = false;
            break ;
          case i4Dbutton9 :                                      // process_4Dbutton9 process Button (Station #10)
            Station = "https://digitalstreams.mediaworks.nz/edge_net/playlist.m3u8";
            StationName = "The Edge";
            gfx.TWprint(StationName); gfx.TWprintln(" Station Selected");
            gfx.UserImages(i4Dbutton1, 0);
            gfx.UserImages(i4Dbutton2, 0);
            gfx.UserImages(i4Dbutton3, 0);
            gfx.UserImages(i4Dbutton4, 0);
            gfx.UserImages(i4Dbutton5, 0);
            gfx.UserImages(i4Dbutton6, 0);
            gfx.UserImages(i4Dbutton7, 0);
            gfx.UserImages(i4Dbutton8, 0);
            gfx.UserImages(i4Dbutton9, 2);
            gfx.UserImages(i4Dbutton10, 0);
            audio.stopSong();
            Play = false;
            break ;

        }                                                     // end button selection **do not alter, remove or duplicate this line**
    }
  }

  // VU Meter of Audio Signal
  vulev[vucount] = audio.getVUlevel();
  vucount++;
  if (vucount >= 20)
  {
    vucount = 0;
    vuMeter(audio.getVUlevel());
  }

  audio.loop();
  vTaskDelay(1);

  // Prevents repeated actions on Play/Stop buttons, only acts if they have changed
  if(Play != lastPlay)
  {
    // Checks if a Station has been selected
    if(Station != NULL)
    {
      // Play button
      if (Play == true)
      {
        audio.connecttohost(Station.c_str());
        digitalWrite(AMP_CTRL, HIGH); // Enable Amplifier
        gfx.TWprint("Playing Station "); gfx.TWprintln(StationName);
        lastPlay = true;
      }
      // Stop button
      else
      {
        gfx.TWprintln("Playing Stopped");
        audio.stopSong();
        digitalWrite(AMP_CTRL, LOW); // Disable Amplifier
        lastPlay = false;
      }
    }
    // No Station selected
    else
    {
      gfx.TWprintln("Select a Station first");
      Play = false;
    }
  }

  // Prevents repeated actions on Volume, only acts if it changed
  if(Volume != lastVolume)
  {
    es.setVolume(Volume);
    gfx.TWprint("Volume set to "); gfx.TWprintln(Volume);
    lastVolume = Volume;
  }

  // Reconnect WiFi
  if(ReconnectWiFi == true)
  {
    ReconnectWiFi = false;
    audio.stopSong();
    digitalWrite(AMP_CTRL, LOW); // Disable Amplifier

    Play = false;
    lastPlay = false;

    WiFi.disconnect();
    WiFi.begin(ssid.c_str(), password.c_str());
    gfx.TWprint("Reconnecting to WiFi");
    while (WiFi.status() != WL_CONNECTED)
    {
      delay(1500);
      gfx.TWprint(".");
    }
    gfx.TWprint("\nWiFi Conencted to "); gfx.TWprintln(ssid);
  }

  // Brightness control, 0-14 -> 1-15 (never goes to 0 else you can loose the location to increase brightness again in the demo)
  if(Brightness != lastBrightness)
  {
    gfx.Contrast(Brightness);
    gfx.TWprint("Brightness set to: "); gfx.TWprintln(Brightness);
    lastBrightness = Brightness;
  }
}

// VU Meter based on Sound levels
void vuMeter(int vu)
{
  uint16_t col;
  uint16_t r, b;
  int x = 780;
  int y = 450;
  gfx.StartWrite();
  for (int n = 0; n < 30; n++)
  {
    r = n;
    b = 31 - n;  //(8 * n);
    col = (r << 11) + b;
    if ((n * 9) < (vu >> 7))
    {
      gfx.RectangleFilled(x + (n * 12), y, x + (n * 12) + 10, y + 16, col);
      //gfx.RectangleFilledPPA(x + (n * 12), y, x + (n * 12) + 10, y + 16, col);  // PPA Version
    }
    else
    {
      gfx.AlphaBlendLevel(127);
      gfx.AlphaBlend(ON);
      gfx.RectangleFilled(x + (n * 12), y, x + (n * 12) + 10, y + 16, 0x1126);
      //gfx.RectangleFilledPPA(x + (n * 12), y, x + (n * 12) + 10, y + 16, 0x1126);  // PPA Version
      gfx.AlphaBlend(OFF);
    }
  }
  gfx.EndWrite();
}

// Streaming data - very dependant on Station and its capability. Uncomment to try various info output.
void my_audio_info(Audio::msg_t m)
{
  switch(m.e)
  {
    case Audio::evt_info:           /*gfx.TWprint("info: ....... "); gfx.TWprintln(String(m.msg));*/ break;
    case Audio::evt_eof:            /*gfx.TWprint("end of file:  "); gfx.TWprintln(String(m.msg));*/ break;
    case Audio::evt_bitrate:        /*gfx.TWprint("bitrate: .... "); gfx.TWprintln(String(m.msg));*/ break; // icy-bitrate or bitrate from metadata
    case Audio::evt_icyurl:         /*gfx.TWprint("icy URL: .... "); gfx.TWprintln(String(m.msg));*/ break;
    case Audio::evt_id3data:        /*gfx.TWprint("ID3 data: ... "); gfx.TWprintln(String(m.msg));*/ break; // id3-data or metadata
    case Audio::evt_lasthost:       /*gfx.TWprint("last URL: ... "); gfx.TWprintln(String(m.msg));*/ break;
    case Audio::evt_name:           /*gfx.TWprint("Station Name: "); gfx.TWprintln(String(m.msg));*/ break; // station name or icy-name
    case Audio::evt_streamtitle:    gfx.TWprint("Stream Title: "); gfx.TWprintln(String(m.msg)); break;
    case Audio::evt_icylogo:        /*gfx.TWprint("icy logo: ... "); gfx.TWprintln(String(m.msg));*/ break;
    case Audio::evt_icydescription: /*gfx.TWprint("icy descr: .. "); gfx.TWprintln(String(m.msg));*/ break;
    case Audio::evt_image:          /*for(int i = 0; i < m.vec.size(); i += 2){
                                    gfxTWprint("cover image:  segment %02i, pos %07lu, len %05lu\n", i / 2, m.vec[i], m.vec[i + 1]);}*/ break; // APIC
    case Audio::evt_lyrics:         /*gfx.TWprint("sync lyrics:  "); gfx.TWprintln(String(m.msg));*/ break;
    case Audio::evt_log   :         /*gfx.TWprint("audio_logs:   "); gfx.TWprintln(String(m.msg));*/ break;
    default:                        /*gfx.TWprint("message:..... "); gfx.TWprintln(String(m.msg));*/ break;
  }
}

