Skip to content

Commit

Permalink
mpd: queue list
Browse files Browse the repository at this point in the history
  • Loading branch information
vroland committed Dec 3, 2020
1 parent 734268a commit 9baa591
Show file tree
Hide file tree
Showing 10 changed files with 75,248 additions and 13,182 deletions.
20 changes: 20 additions & 0 deletions examples/mpd_status/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FONT_DIR ?= /usr/share/fonts/TTF
FONTCONVERT ?= ../../scripts/fontconvert.py
IMGCONVERT ?= ../../scripts/imgconvert.py

.PHONY: fonts main/*
fonts: main/default_album.h main/firasans_20.h main/firasans_16_bold.h main/firasans_16.h main/firasans_24.h


main/default_album.h:
python3 $(IMGCONVERT) -n DefaultAlbum -i default_album.png -o $@

main/firasans_%.h:
python3 $(FONTCONVERT) FiraSans$* $* $(FONT_DIR)/FiraSans-Light.ttf $(FONT_DIR)/Symbola.ttf $(FONT_DIR)/FiraCode-Regular.ttf --compress > $@

main/firasans_%_bold.h:
python3 $(FONTCONVERT) FiraSans$*_Bold $* $(FONT_DIR)/FiraSans-Bold.ttf $(FONT_DIR)/Symbola.ttf $(FONT_DIR)/FiraCode-Bold.ttf --compress > $@

clean:
rm main/firasans_*.h
rm main/default_album.h
704 changes: 704 additions & 0 deletions examples/mpd_status/main/default_album.h

Large diffs are not rendered by default.

8,199 changes: 0 additions & 8,199 deletions examples/mpd_status/main/firasans.h

This file was deleted.

4,912 changes: 0 additions & 4,912 deletions examples/mpd_status/main/firasans_12pt.h

This file was deleted.

15,607 changes: 15,607 additions & 0 deletions examples/mpd_status/main/firasans_16.h

Large diffs are not rendered by default.

15,906 changes: 15,906 additions & 0 deletions examples/mpd_status/main/firasans_16_bold.h

Large diffs are not rendered by default.

19,290 changes: 19,290 additions & 0 deletions examples/mpd_status/main/firasans_20.h

Large diffs are not rendered by default.

23,547 changes: 23,547 additions & 0 deletions examples/mpd_status/main/firasans_24.h

Large diffs are not rendered by default.

228 changes: 168 additions & 60 deletions examples/mpd_status/main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,28 @@
#include <string.h>

#include "epd_driver.h"
#include "firasans.h"
#include "firasans_16.h"
#include "firasans_16_bold.h"
#include "firasans_20.h"
#include "firasans_24.h"
#include "default_album.h"
#include "mpd/client.h"
#include "wifi_config.h"
#include "mpd_image.h"
#include "mpd_info.h"
#include "wifi_config.h"

uint8_t *img_buf;
const int queue_x_start = 900;
const int album_cover_x = 100;
const int album_cover_y = 100;
const int queue_x_end = 1500;
const int queue_y_start = 100;

void delay(uint32_t millis) { vTaskDelay(millis / portTICK_PERIOD_MS); }

uint32_t millis() { return esp_timer_get_time() / 1000; }

static bool got_ip = false;

static album_cover_t *album_cover = NULL;
static mpd_playback_info_t *playback_info = NULL;

static void event_handler(void *arg, esp_event_base_t event_base,
int32_t event_id, void *event_data) {
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
Expand All @@ -50,39 +55,45 @@ static void event_handler(void *arg, esp_event_base_t event_base,
}
}

void show_status(struct mpd_status *status, struct mpd_song *song) {
memset(img_buf, 255, EPD_WIDTH / 2 * EPD_HEIGHT);
void show_status(struct mpd_status *status, struct mpd_song *song,
uint8_t *img_buf, int album_height) {

int cursor_x = 700;
int cursor_y = 200;
int cursor_x = album_cover_x;
int cursor_y = album_height + 100;
if (mpd_song_get_tag(song, MPD_TAG_TITLE, 0)) {
write_string((GFXfont*)&FiraSans, (char*)mpd_song_get_tag(song, MPD_TAG_TITLE, 0), &cursor_x, &cursor_y, img_buf);
write_string((GFXfont *)&FiraSans24,
(char *)mpd_song_get_tag(song, MPD_TAG_TITLE, 0), &cursor_x,
&cursor_y, img_buf);
}

if (mpd_song_get_tag(song, MPD_TAG_ALBUM, 0)) {
cursor_x = 700;
cursor_y = 200 + FiraSans.advance_y * 2;
write_string((GFXfont*)&FiraSans, (char*)mpd_song_get_tag(song, MPD_TAG_ALBUM, 0), &cursor_x,
cursor_x = album_cover_x;
cursor_y = album_height + 100 + FiraSans24.advance_y + FiraSans24.advance_y;
write_string((GFXfont *)&FiraSans20,
(char *)mpd_song_get_tag(song, MPD_TAG_ALBUM, 0), &cursor_x,
&cursor_y, img_buf);
}

if (mpd_song_get_tag(song, MPD_TAG_ARTIST, 0)) {
cursor_x = 700;
cursor_y = 200 + FiraSans.advance_y * 3;
write_string((GFXfont*)&FiraSans, (char*)mpd_song_get_tag(song, MPD_TAG_ARTIST, 0), &cursor_x,
cursor_x = album_cover_x;
cursor_y =
album_height + 100 + FiraSans24.advance_y + FiraSans20.advance_y * 2;
write_string((GFXfont *)&FiraSans20,
(char *)mpd_song_get_tag(song, MPD_TAG_ARTIST, 0), &cursor_x,
&cursor_y, img_buf);
}
}

void handle_error(struct mpd_connection **c) {
enum mpd_error err = mpd_connection_get_error(*c);
if (err == MPD_ERROR_SUCCESS) return;
if (err == MPD_ERROR_SUCCESS)
return;

ESP_LOGE("mpd", "%d %s\n", err, mpd_connection_get_error_message(*c));
// error is not recoverable
if (!mpd_connection_clear_error(*c)) {
mpd_connection_free(*c);
*c = NULL;
mpd_connection_free(*c);
*c = NULL;
}
}

Expand All @@ -95,7 +106,6 @@ static void print_tag(const struct mpd_song *song, enum mpd_tag_type type,
printf("%s: %s\n", label, value);
}


void epd_task() {
epd_init();

Expand Down Expand Up @@ -139,6 +149,17 @@ void epd_task() {
delay(100);
}

uint8_t *img_buf =
heap_caps_malloc(EPD_WIDTH / 2 * EPD_HEIGHT, MALLOC_CAP_SPIRAM);

album_cover_t *album_cover = NULL;
mpd_playback_info_t *playback_info = NULL;


memset(img_buf, 255, EPD_WIDTH / 2 * EPD_HEIGHT);

bool init = true;

struct mpd_connection *mpd_conn = NULL;
while (true) {
// connect / reconnect
Expand All @@ -153,81 +174,168 @@ void epd_task() {
printf("\n");
}

mpd_run_idle(mpd_conn);
handle_error(&mpd_conn);
if (!init) {
mpd_run_idle(mpd_conn);
handle_error(&mpd_conn);

mpd_response_finish(mpd_conn);
handle_error(&mpd_conn);
mpd_response_finish(mpd_conn);
handle_error(&mpd_conn);
}

mpd_playback_info_t* new_info = fetch_playback_info(mpd_conn);
mpd_playback_info_t *new_info = fetch_playback_info(mpd_conn);
handle_error(&mpd_conn);
bool do_update = true;

if (playback_info != NULL && playback_info != NULL) {
do_update = memcmp(new_info->hash, playback_info->hash, crypto_generichash_BYTES) != 0;
bool do_update = false;

if (playback_info != NULL && new_info != NULL) {
do_update = memcmp(new_info->hash, playback_info->hash,
crypto_generichash_BYTES) != 0;
}

if (playback_info) {
if (playback_info)
free_playback_info(playback_info);
}

playback_info = new_info;

if (new_info == NULL) {
ESP_LOGW("main", "update is invalid!");
// no song playing
if (new_info == NULL && (playback_info != new_info || init)) {
ESP_LOGW("main", "no song playing");
epd_poweron();
epd_draw_image(epd_full_screen(), img_buf, WHITE_ON_WHITE);
epd_clear_area_cycles(epd_full_screen(), 2, 20);
memset(img_buf, 255, EPD_WIDTH / 2 * EPD_HEIGHT);
int x = album_cover_x;
int y = album_cover_y;
write_string((GFXfont*)&FiraSans24, "Warteschlange leer.", &x, &y, img_buf);
epd_draw_grayscale_image(epd_full_screen(), img_buf);
epd_poweroff();
}

if (do_update && new_info) {

if ((do_update || init) && new_info != NULL) {
epd_poweron();
{
int x = 50;
int y = EPD_HEIGHT - 100;
write_string((GFXfont*)&FiraSans, "updating...", &x, &y, NULL);
}
epd_draw_image(epd_full_screen(), img_buf, WHITE_ON_WHITE);
epd_clear_area_cycles(epd_full_screen(), 2, 20);
epd_poweroff();

char *album = (char*)mpd_song_get_tag(playback_info->current_song, MPD_TAG_ALBUM, 0);
if (album_cover == NULL || album_cover->identifier == NULL || album == NULL || strncmp(album_cover->identifier, album, 128) != 0) {

memset(img_buf, 255, EPD_WIDTH / 2 * EPD_HEIGHT);
mpd_send_list_queue_meta(mpd_conn);
handle_error(&mpd_conn);

int queue_y = queue_y_start + FiraSans20.advance_y;
epd_draw_line(queue_x_start, queue_y_start, queue_x_end, queue_y_start + 1, 0, img_buf);
struct mpd_entity *entity;
while ((entity = mpd_recv_entity(mpd_conn)) != NULL) {
handle_error(&mpd_conn);
const struct mpd_song *song;
const struct mpd_directory *dir;
const struct mpd_playlist *pl;

switch (mpd_entity_get_type(entity)) {
case MPD_ENTITY_TYPE_UNKNOWN:
printf("Unknown type\n");
break;

case MPD_ENTITY_TYPE_SONG:
song = mpd_entity_get_song(entity);
unsigned duration = mpd_song_get_duration(song);

GFXfont *font = (GFXfont *)&FiraSans16;
if (strcmp(mpd_song_get_uri(song),
mpd_song_get_uri(playback_info->current_song)) == 0) {
font = (GFXfont *)&FiraSans16_Bold;
}

int queue_x = queue_x_start + 60;
char timestr[12] = {0};
snprintf(timestr, 12, "%02d:%02d", duration / 60, duration % 60);
int t_x = 0, t_y = 0, t_x1, t_y1, t_h, w_time = 0;
get_text_bounds(font, timestr, &t_x, &t_y, &t_x1, &t_y1, &w_time, &t_h, NULL);

int w_track = 0;
char* track = (char *)mpd_song_get_tag(song, MPD_TAG_TRACK, 0);
get_text_bounds(font, track, &t_x, &t_y, &t_x1, &t_y1, &w_track, &t_h, NULL);

int timestamp_x = queue_x_end - w_time;
int timestamp_y = queue_y;
int track_x = queue_x_start;
int track_y = queue_y;
char* title = (char *)mpd_song_get_tag(song, MPD_TAG_TITLE, 0);
write_string(font, title, &queue_x, &queue_y, img_buf);
write_string(font, track, &track_x, &track_y, img_buf);
write_string(font, timestr, &timestamp_x, &timestamp_y, img_buf);
break;

case MPD_ENTITY_TYPE_DIRECTORY:
dir = mpd_entity_get_directory(entity);
printf("directory: %s\n", mpd_directory_get_path(dir));
break;

case MPD_ENTITY_TYPE_PLAYLIST:
pl = mpd_entity_get_playlist(entity);
ESP_LOGI("mpd", "playlist: %s", mpd_playlist_get_path(pl));
break;
}

mpd_entity_free(entity);
}
epd_draw_line(queue_x_start, queue_y - FiraSans16.advance_y / 2, queue_x_end, queue_y + 1 - FiraSans16.advance_y / 2, 0, img_buf);

mpd_response_finish(mpd_conn);
handle_error(&mpd_conn);

char *album = (char *)mpd_song_get_tag(playback_info->current_song,
MPD_TAG_ALBUM, 0);
if (album_cover == NULL || album_cover->identifier == NULL ||
album == NULL || strncmp(album_cover->identifier, album, 128) != 0) {
if (album_cover) {
free_album_cover(album_cover);
album_cover = NULL;
}
album_cover = readpicture(mpd_conn, (char*)mpd_song_get_uri(playback_info->current_song), album);
album_cover = readpicture(
mpd_conn, (char *)mpd_song_get_uri(playback_info->current_song),
album);
}

show_status(playback_info->status, playback_info->current_song);

if (album_cover) {
int album_height = 700;
if (album_cover != NULL) {
Rect_t area = {
.width = album_cover->width,
.height = album_cover->height,
.x = 50,
.y = (825 - album_cover->height) / 2,
.width = album_cover->width,
.height = album_cover->height,
.x = album_cover_x,
.y = album_cover_y,
};
printf("album cover dimensions: %dx%d\n", album_cover->width, album_cover->height);
printf("album cover dimensions: %dx%d\n", album_cover->width,
album_cover->height);
album_height = album_cover->height;
epd_copy_to_framebuffer(area, album_cover->data, img_buf);
} else {
Rect_t area = {
.width = DefaultAlbum_width,
.height = DefaultAlbum_height,
.x = album_cover_x,
.y = album_cover_y,
};
printf("album cover dimensions: %dx%d\n", DefaultAlbum_width, DefaultAlbum_height);
album_height = DefaultAlbum_height;
epd_copy_to_framebuffer(area, (uint8_t*)DefaultAlbum_data, img_buf);
}

show_status(playback_info->status, playback_info->current_song, img_buf, album_cover_y + album_height);

epd_poweron();
epd_clear();
epd_draw_grayscale_image(epd_full_screen(), img_buf);
epd_poweroff();
}

init = false;
}
}

void app_main() {
// copy the image data to SRAM for faster display time
img_buf = (uint8_t *)heap_caps_malloc(EPD_WIDTH * EPD_HEIGHT / 2,
MALLOC_CAP_SPIRAM);
if (img_buf == NULL) {
ESP_LOGE("epd_task", "Could not allocate framebuffer in PSRAM!");
}

// memcpy(img_buf, dragon_data, EPD_WIDTH * EPD_HEIGHT / 2);
heap_caps_print_heap_info(MALLOC_CAP_INTERNAL);
heap_caps_print_heap_info(MALLOC_CAP_SPIRAM);

xTaskCreatePinnedToCore(&epd_task, "epd task", 10000, NULL, 2, NULL, 1);
xTaskCreatePinnedToCore(&epd_task, "epd task", 1 << 15, NULL, 2, NULL, 1);
}

0 comments on commit 9baa591

Please sign in to comment.