diff --git a/img/plex_background.jpg b/img/plex_background.jpg new file mode 100644 index 0000000..5af4534 Binary files /dev/null and b/img/plex_background.jpg differ diff --git a/src/config.cpp b/src/config.cpp index c98d03a..b853a47 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -46,6 +46,9 @@ const char* IMAGE_LOCATIONS[] = { "shower.png", "snowday.png", "snownight.png", + + //plex + "plex_background.jpg", }; size_t IMAGE_LOCATIONS_LENGTH = sizeof(IMAGE_LOCATIONS)/sizeof(IMAGE_LOCATIONS[0]); diff --git a/src/panel/plex.cpp b/src/panel/plex.cpp index acd96a8..0667727 100644 --- a/src/panel/plex.cpp +++ b/src/panel/plex.cpp @@ -78,8 +78,28 @@ void plex::update(){ //parse the result json_doc.Parse(json_string.c_str()); + std::cerr << json_string << "\n"; + //update internal state - //const rapidjson::Value& curr_entry = json_doc["value"]; + rapidjson::Value& curr_entry = json_doc["response"]["data"]["data"]; + + for(short i = 0; i < 4; ++i){ + entries.push_back({ + truncate(curr_entry[i]["friendly_name"].GetString(), + PLEX_MAX_STRING_LENGTH), + truncate(curr_entry[i]["ip_address"].GetString(), + PLEX_MAX_STRING_LENGTH), + truncate(curr_entry[i]["title"].GetString(), + PLEX_MAX_STRING_LENGTH), + truncate(curr_entry[i]["state"].IsNull() ? "Historical" : "Playing", + PLEX_MAX_STRING_LENGTH), + }); + + std::cerr << entries[i].friendly_name << "\n"; + std::cerr << entries[i].ip_address << "\n"; + std::cerr << entries[i].title << "\n"; + std::cerr << entries[i].state << "\n"; + } } @@ -88,15 +108,216 @@ void plex::update(){ // displayed, based on data in the json feed void plex::update_texture(){ std::cerr << "PLEX::UPDATE_TEXTURE\n"; + uint8_t o_red, o_green, o_blue, o_alpha; SDL_Rect tgt; + + //save the old colors + SDL_GetRenderDrawColor(board::getRenderer(), &o_red, + &o_green, &o_blue, &o_alpha); SDL_SetRenderTarget(board::getRenderer(), _texture); SDL_RenderClear(board::getRenderer()); + //set the new color + SDL_SetRenderDrawColor(board::getRenderer(), + PLEX_BGBOX_RED, PLEX_BGBOX_GREEN, + PLEX_BGBOX_BLUE, PLEX_BGBOX_ALPHA); + //background image + SDL_RenderCopy(board::getRenderer(), + board::getImage("plex_background.jpg"), NULL, NULL); + + constexpr int GAP_SIZE = 10; + + //draw the outline rectangles + tgt.x = GAP_SIZE; + tgt.y = DEF_OVERLAY_BAR_HEIGHT + GAP_SIZE; + tgt.w = (SCREEN_WIDTH / 3) - (2*GAP_SIZE); + tgt.h = (SCREEN_HEIGHT / 2) - DEF_OVERLAY_BAR_HEIGHT - (2*GAP_SIZE); + SDL_RenderFillRect(board::getRenderer(), &tgt); + + tgt.x = GAP_SIZE; + tgt.y = (SCREEN_HEIGHT / 2) + GAP_SIZE; + tgt.w = (SCREEN_WIDTH / 3) - (2*GAP_SIZE); + tgt.h = (SCREEN_HEIGHT / 2) - DEF_OVERLAY_BAR_HEIGHT - (2*GAP_SIZE); + SDL_RenderFillRect(board::getRenderer(), &tgt); + + tgt.x = (SCREEN_WIDTH / 3) + GAP_SIZE; + tgt.y = DEF_OVERLAY_BAR_HEIGHT + GAP_SIZE; + tgt.w = (SCREEN_WIDTH / 3) - (2*GAP_SIZE); + tgt.h = (SCREEN_HEIGHT / 2) - DEF_OVERLAY_BAR_HEIGHT - (2*GAP_SIZE); + SDL_RenderFillRect(board::getRenderer(), &tgt); + + tgt.x = (SCREEN_WIDTH / 3) + GAP_SIZE; + tgt.y = (SCREEN_HEIGHT / 2) + GAP_SIZE; + tgt.w = (SCREEN_WIDTH / 3) - (2*GAP_SIZE); + tgt.h = (SCREEN_HEIGHT / 2) - DEF_OVERLAY_BAR_HEIGHT - (2*GAP_SIZE); + SDL_RenderFillRect(board::getRenderer(), &tgt); + + tgt.x = ((2*SCREEN_WIDTH) / 3) + GAP_SIZE; + tgt.y = DEF_OVERLAY_BAR_HEIGHT + GAP_SIZE; + tgt.w = (SCREEN_WIDTH / 3) - (2*GAP_SIZE); + tgt.h = (SCREEN_HEIGHT) - (2*DEF_OVERLAY_BAR_HEIGHT) - (2*GAP_SIZE); + SDL_RenderFillRect(board::getRenderer(), &tgt); + + //draw info for first box + { + tgt.x = GAP_SIZE; + tgt.y = DEF_OVERLAY_BAR_HEIGHT + GAP_SIZE; + constexpr int index = 0; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].title.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].title, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + tgt.y += tgt.h; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].friendly_name.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].friendly_name, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + tgt.y += tgt.h; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].ip_address.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].ip_address, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + tgt.y += tgt.h; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].state.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].state, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + } + + //draw the second box + { + tgt.x = GAP_SIZE; + tgt.y = (SCREEN_HEIGHT / 2) + GAP_SIZE; + constexpr int index = 1; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].title.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].title, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + tgt.y += tgt.h; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].friendly_name.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].friendly_name, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + tgt.y += tgt.h; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].ip_address.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].ip_address, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + tgt.y += tgt.h; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].state.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].state, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + } + + //third box + { + tgt.x = (SCREEN_WIDTH / 3) + GAP_SIZE; + tgt.y = DEF_OVERLAY_BAR_HEIGHT + GAP_SIZE; + constexpr int index = 2; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].title.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].title, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + tgt.y += tgt.h; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].friendly_name.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].friendly_name, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + tgt.y += tgt.h; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].ip_address.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].ip_address, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + tgt.y += tgt.h; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].state.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].state, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + } + + //draw info for fourth box + { + tgt.x = (SCREEN_WIDTH / 3) + GAP_SIZE; + tgt.y = (SCREEN_HEIGHT / 2) + GAP_SIZE; + constexpr int index = 3; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].title.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].title, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + tgt.y += tgt.h; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].friendly_name.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].friendly_name, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + tgt.y += tgt.h; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].ip_address.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].ip_address, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + tgt.y += tgt.h; + TTF_SizeText(board::getFont( {"Roboto_Mono/RobotoMono-Medium.ttf", 28 } ), + entries[index].state.c_str(), + &tgt.w, &tgt.h); + SDL_RenderCopy(board::getRenderer(), + board::getString(entries[index].state, + {"Roboto_Mono/RobotoMono-Medium.ttf", 28 }), + NULL, &tgt); + } SDL_SetRenderTarget(board::getRenderer(), NULL); + + //reset back to the old render color + SDL_SetRenderDrawColor(board::getRenderer(), + o_red, o_green, o_blue, o_alpha); } /////////////////////////////////////// @@ -114,6 +335,18 @@ void plex::initTexture(){ } } +/////////////////////////////////////// +// Helper function to truncate a string with an elipsis +std::string plex::truncate(std::string str, size_t width, bool show_ellipsis){ + if(str.length() > width){ + if(show_ellipsis) + return str.substr(0, width - 3) + "..."; + else + return str.substr(0, width); + } + return str; +} + /////////////////////////////////////// // Curl callback function size_t dashboard::panel::plex::curl_callback(void* contents, size_t size, diff --git a/src/panel/plex.hpp b/src/panel/plex.hpp index af6bd8b..a5abbfd 100644 --- a/src/panel/plex.hpp +++ b/src/panel/plex.hpp @@ -18,6 +18,7 @@ #include #include #include +#include namespace dashboard::panel { class plex : public panel { @@ -33,10 +34,22 @@ namespace dashboard::panel { void update_texture(); void initTexture(); + std::string truncate(std::string, size_t, bool = true); + CURL* api_curl; std::string json_string; rapidjson::Document json_doc; + struct plex_entry { + std::string friendly_name; + std::string ip_address; + std::string title; + std::string state; + }; + + std::vector entries; + + std::chrono::time_point _last_update; std::chrono::milliseconds _update_interval; }; diff --git a/src/panel/plex_config.hpp b/src/panel/plex_config.hpp index a6faacc..457d407 100644 --- a/src/panel/plex_config.hpp +++ b/src/panel/plex_config.hpp @@ -6,13 +6,18 @@ #pragma once +#include "def_overlay_config.hpp" + namespace dashboard::panel { //This will be displayed at the top left on the status bar. Set to a blank //string to not show anything constexpr char PLEX_TITLE[] = "Plex"; //Tautili endpoint - constexpr char PLEX_URL_SOURCE[] = "http://192.168.1.104:8181/api/v2?apikey=&cmd="; + constexpr char PLEX_URL_SOURCE[] = "http://192.168.1.104:8181/api/v2?apikey=64af06e0497342f7a5862462ddbbd309&cmd=get_history&length=5"; + + //How many characters of a show title should we show? + constexpr size_t PLEX_MAX_STRING_LENGTH = 35; //Default time the slid is shown on screen, in ms //Default 15s @@ -22,4 +27,11 @@ namespace dashboard::panel { //Default 30s constexpr size_t PLEX_UPDATE_INTERVAL = 30000; + //Color for background bounding boxes + constexpr uint8_t PLEX_BGBOX_RED = 0xD3; + constexpr uint8_t PLEX_BGBOX_GREEN = 0xD3; + constexpr uint8_t PLEX_BGBOX_BLUE = 0xD3; + constexpr uint8_t PLEX_BGBOX_ALPHA = 0x7F; + + }