From 11bbce74479994e8ee9420112f80a01eb2944f28 Mon Sep 17 00:00:00 2001
From: Bent Bisballe Nyeng <deva@aasimon.org>
Date: Thu, 15 Sep 2016 19:08:08 +0200
Subject: Added new inline display for showing load progress.

---
 plugin/drumgizmo.ttl       |  2 +
 plugin/drumgizmo_plugin.cc | 97 ++++++++++++++++++++++++++++++++++++++++++++++
 plugin/drumgizmo_plugin.h  | 34 ++++++++++++++++
 plugingui/pixelbuffer.cc   |  8 +++-
 plugingui/pixelbuffer.h    | 18 +++++----
 5 files changed, 149 insertions(+), 10 deletions(-)

diff --git a/plugin/drumgizmo.ttl b/plugin/drumgizmo.ttl
index 2e9b930..e5b163d 100644
--- a/plugin/drumgizmo.ttl
+++ b/plugin/drumgizmo.ttl
@@ -22,6 +22,7 @@
 @prefix pprops: <http://lv2plug.in/ns/ext/port-props#> .
 @prefix lv2:    <http://lv2plug.in/ns/lv2core#> .
 @prefix rdfs:   <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix idpy:   <http://harrisonconsoles.com/lv2/inlinedisplay#> .
 
 <http://drumgizmo.org/lv2#ui>
     a ui:X11UI ;
@@ -43,6 +44,7 @@
 	doap:license <http://opensource.org/licenses/gpl-3.0> ;
 	lv2:optionalFeature <http://lv2plug.in/ns/ext/uri-map> ;
 	lv2:optionalFeature <http://lv2plug.in/ns/ext/event> ;
+	lv2:optionalFeature idpy:queue_draw ;
   lv2:extensionData state:interface ;
 	lv2:port [
     a lv2:InputPort, lv2:ControlPort ;
diff --git a/plugin/drumgizmo_plugin.cc b/plugin/drumgizmo_plugin.cc
index fa51575..9414914 100644
--- a/plugin/drumgizmo_plugin.cc
+++ b/plugin/drumgizmo_plugin.cc
@@ -156,6 +156,103 @@ void DrumGizmoPlugin::process(size_t pos,
 	this->output_samples = nullptr;
 }
 
+bool DrumGizmoPlugin::hasInlineGUI()
+{
+	return true;
+}
+
+class InlinePixelBufferAlpha
+	: public GUI::PixelBufferAlpha
+{
+public:
+	InlinePixelBufferAlpha(Plugin::InlineDrawContext& context)
+	{
+		buf = context.data;
+		width = context.width;
+		height = context.height;
+		x = 0;
+		y = 0;
+	}
+};
+
+class InlineCanvas
+	: public GUI::Canvas
+{
+public:
+	InlineCanvas(Plugin::InlineDrawContext& context)
+		: pixbuf(context)
+	{
+	}
+
+	GUI::PixelBufferAlpha& GetPixelBuffer()
+	{
+		return pixbuf;
+	}
+	void beginPaint() {}
+	void endPaint() {}
+
+private:
+	InlinePixelBufferAlpha pixbuf;
+};
+
+void DrumGizmoPlugin::onInlineRedraw(std::size_t width,
+                                     std::size_t max_height,
+                                     InlineDrawContext& context)
+{
+	std::size_t height = std::min(11u, max_height);
+	if(!context.data ||
+	   (context.width != width) ||
+	   (context.height != height) ||
+	   settingsGetter.number_of_files.hasChanged() ||
+	   settingsGetter.number_of_files_loaded.hasChanged() ||
+	   settingsGetter.drumkit_load_status.hasChanged())
+	{
+		context.width = width;
+		context.height = height;
+		assert(context.width * context.height <= sizeof(inlineDisplayBuffer));
+)
+		context.data = (unsigned char*)inlineDisplayBuffer;
+		box.setSize(context.width, context.height);
+
+		InlineCanvas canvas(context);
+		GUI::Painter painter(canvas);
+		painter.clear();
+		painter.drawImage(0, 1, box);
+
+		double progress =
+			(double)settingsGetter.number_of_files_loaded.getValue() /
+			(double)settingsGetter.number_of_files.getValue();
+
+		int brd = 4;
+		int val = (width - (2 * brd)) * progress;
+
+		switch(settingsGetter.drumkit_load_status.getValue())
+		{
+		case LoadStatus::Error:
+			bar_red.setSize(val, height);
+			painter.drawImage(brd, 0, bar_red);
+			break;
+		case LoadStatus::Done:
+			bar_green.setSize(val, height);
+			painter.drawImage(brd, 0, bar_green);
+			break;
+		case LoadStatus::Loading:
+		case LoadStatus::Idle:
+			bar_blue.setSize(val, height);
+			painter.drawImage(brd, 0, bar_blue);
+			break;
+		}
+
+		// Convert to correct pixel format
+		for(std::size_t i = 0; i < context.height * context.width; ++i)
+		{
+			std::uint32_t pixel = inlineDisplayBuffer[i];
+			unsigned char* p = (unsigned char*)&pixel;
+			inlineDisplayBuffer[i] = pgzRGBA(p[0], p[1], p[2], p[3]);
+		}
+	}
+}
+
 bool DrumGizmoPlugin::hasGUI()
 {
 	return true;
diff --git a/plugin/drumgizmo_plugin.h b/plugin/drumgizmo_plugin.h
index 2e3da26..de4f4af 100644
--- a/plugin/drumgizmo_plugin.h
+++ b/plugin/drumgizmo_plugin.h
@@ -50,6 +50,9 @@
 #include <audiooutputengine.h>
 #include <plugingui.h>
 
+#include <texturedbox.h>
+#include <imagecache.h>
+
 class DrumGizmoPlugin
 #ifdef LV2
 	: public PluginLV2
@@ -94,6 +97,14 @@ public:
 	             const std::vector<float*>& output_samples,
 	             size_t count) override;
 
+	//
+	// Inline GUI
+	//
+	bool hasInlineGUI() override;
+	void onInlineRedraw(std::size_t width,
+	                    std::size_t max_height,
+	                    InlineDrawContext& context) override;
+
 	//
 	// GUI
 	//
@@ -174,7 +185,30 @@ private:
 
 	Settings settings;
 	ConfigStringIO config_string_io;
+	SettingsGetter settingsGetter{settings};
+
+	GUI::ImageCache imageCache;
+	GUI::TexturedBox box{imageCache, ":progress.png",
+			0, 0, // atlas offset (x, y)
+			6, 1, 6, // dx1, dx2, dx3
+			11, 0, 0}; // dy1, dy2, dy3
+
+	GUI::TexturedBox bar_red{imageCache, ":progress.png",
+			13, 0, // atlas offset (x, y)
+			2, 1, 2, // dx1, dx2, dx3
+			11, 0, 0}; // dy1, dy2, dy3
+
+	GUI::TexturedBox bar_green{imageCache, ":progress.png",
+			18, 0, // atlas offset (x, y)
+			2, 1, 2, // dx1, dx2, dx3
+			11, 0, 0}; // dy1, dy2, dy3
+
+	GUI::TexturedBox bar_blue{imageCache, ":progress.png",
+			23, 0, // atlas offset (x, y)
+			2, 1, 2, // dx1, dx2, dx3
+			11, 0, 0}; // dy1, dy2, dy3
 
 	std::shared_ptr<GUI::PluginGUI> plugin_gui;
 	std::shared_ptr<DrumGizmo> drumgizmo;
+	std::uint32_t inlineDisplayBuffer[1024*1024];
 };
diff --git a/plugingui/pixelbuffer.cc b/plugingui/pixelbuffer.cc
index 906e4d6..5d032b4 100644
--- a/plugingui/pixelbuffer.cc
+++ b/plugingui/pixelbuffer.cc
@@ -69,7 +69,8 @@ void PixelBuffer::setPixel(size_t x, size_t y,
 }
 
 PixelBufferAlpha::PixelBufferAlpha(size_t width, size_t height)
-	: buf(nullptr)
+	: managed(true)
+	, buf(nullptr)
 	, x(0)
 	, y(0)
 {
@@ -78,7 +79,10 @@ PixelBufferAlpha::PixelBufferAlpha(size_t width, size_t height)
 
 PixelBufferAlpha::~PixelBufferAlpha()
 {
-	free(buf);
+	if(managed)
+	{
+		free(buf);
+	}
 }
 
 void PixelBufferAlpha::realloc(size_t width, size_t height)
diff --git a/plugingui/pixelbuffer.h b/plugingui/pixelbuffer.h
index 8e7618d..762aaa6 100644
--- a/plugingui/pixelbuffer.h
+++ b/plugingui/pixelbuffer.h
@@ -45,13 +45,14 @@ public:
 	              unsigned char blue,
 	              unsigned char alpha);
 
-	unsigned char* buf;
-	size_t width;
-	size_t height;
+	unsigned char* buf{nullptr};
+	size_t width{0};
+	size_t height{0};
 };
 
 class PixelBufferAlpha {
 public:
+	PixelBufferAlpha() = default;
 	PixelBufferAlpha(size_t width, size_t height);
 	~PixelBufferAlpha();
 
@@ -77,11 +78,12 @@ public:
 	           unsigned char* blue,
 	           unsigned char* alpha);
 
-	unsigned char* buf;
-	size_t width;
-	size_t height;
-	size_t x;
-	size_t y;
+	bool managed{false};
+	unsigned char* buf{nullptr};
+	size_t width{0};
+	size_t height{0};
+	size_t x{0};
+	size_t y{0};
 };
 
 } // GUI::
-- 
cgit v1.2.3