summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2026-10-14 20:03:28 -0700
committerVito Caputo <vcaputo@pengaru.com>2026-10-15 21:23:21 -0700
commit19894057ec25afeab0d10c5e231548a09ea1739d (patch)
tree9b63ce676e36ae2dc87ac906fc4827781b2640c9
parent49d20e4280d8aa6a9b719211a061394fc72d1cf5 (diff)
vcr: include some text chunks in the png destHEADmaster
If the caller has some textual information to embed in the PNG metadata, it should be able to embed it. This adds three: timestamp: always populated with the current time name: always populated with --name arg, or empty payload: made available for customized usage payload is aimed at strobe users who have some context associated with the strobe request they'd like to embed in an easily machine-readable location attached to the png file.
-rw-r--r--src/vcr.c34
-rw-r--r--src/vcr.h2
-rw-r--r--src/vmon.c14
3 files changed, 41 insertions, 9 deletions
diff --git a/src/vcr.c b/src/vcr.c
index a159379..76158f6 100644
--- a/src/vcr.c
+++ b/src/vcr.c
@@ -58,6 +58,7 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdlib.h>
+#include <time.h>
#ifdef USE_XLIB
#include <X11/Xlib.h>
@@ -204,6 +205,7 @@ typedef struct vcr_dest_t {
png_infop info_ctx;
png_structp png_ctx;
FILE *output;
+ png_text text[3];
} png;
#endif /* USE_PNG */
};
@@ -617,7 +619,7 @@ vcr_dest_t * vcr_dest_xpicture_new(vcr_backend_t *vbe, Picture picture)
#ifdef USE_PNG
-vcr_dest_t * vcr_dest_png_new(vcr_backend_t *vbe, FILE *output)
+vcr_dest_t * vcr_dest_png_new(vcr_backend_t *vbe, FILE *output, const char *name, const char *payload)
{
vcr_dest_t *dest;
@@ -651,6 +653,36 @@ vcr_dest_t * vcr_dest_png_new(vcr_backend_t *vbe, FILE *output)
return NULL;
}
+ {
+ time_t now = time(NULL);
+ struct tm *t = localtime(&now);
+ char t_str[32];
+
+ strftime(t_str, sizeof(t_str), "%F %T %Z", t);
+
+ /* we always stick three text fields into the PNGs, the caller is expected to always
+ * provide a `date` style string for timestamp, the chart name for name, and the
+ * payload is flexible. For strobes it's expected the payload may contain some
+ * context about the cause for strobing.
+ */
+ dest->png.text[0].compression = -1; /* none */
+ dest->png.text[0].key = "timestamp";
+ dest->png.text[0].text = t_str;
+ dest->png.text[0].text_length = strlen(t_str);
+
+ dest->png.text[1].compression = -1; /* none */
+ dest->png.text[1].key = "name";
+ dest->png.text[1].text = (char *)name;
+ dest->png.text[1].text_length = name ? strlen(name) : 0;
+
+ dest->png.text[2].compression = -1; /* none */
+ dest->png.text[2].key = "payload";
+ dest->png.text[2].text = (char *)payload;
+ dest->png.text[2].text_length = payload ? strlen(payload) : 0;
+
+ png_set_text(dest->png.png_ctx, dest->png.info_ctx, dest->png.text, 3);
+ }
+
png_init_io(dest->png.png_ctx, output);
return dest;
diff --git a/src/vcr.h b/src/vcr.h
index a9ec6c2..343a26d 100644
--- a/src/vcr.h
+++ b/src/vcr.h
@@ -71,7 +71,7 @@ unsigned vcr_dest_xwindow_get_id(vcr_dest_t *dest);
vcr_dest_t * vcr_dest_xpicture_new(vcr_backend_t *vbe, Picture picture);
#endif /* USE_XLIB */
#ifdef USE_PNG
-vcr_dest_t * vcr_dest_png_new(vcr_backend_t *vbe, FILE *output);
+vcr_dest_t * vcr_dest_png_new(vcr_backend_t *vbe, FILE *output, const char *name, const char *payload);
#endif /* USE_PNG */
vcr_dest_t * vcr_dest_free(vcr_dest_t *dest);
diff --git a/src/vmon.c b/src/vmon.c
index 8e11dca..b42b5df 100644
--- a/src/vmon.c
+++ b/src/vmon.c
@@ -808,7 +808,7 @@ static void vmon_resize(vmon_t *vmon, int width, int height)
/* this is like vmon_snapshot() except in-place at a fixed name; truncates what's there, no atomicity */
-static int vmon_strobe(vmon_t *vmon)
+static int vmon_strobe(vmon_t *vmon, const char *payload)
{
#ifdef USE_PNG
FILE *output;
@@ -823,7 +823,7 @@ static int vmon_strobe(vmon_t *vmon)
{
vcr_dest_t *png_dest;
- png_dest = vcr_dest_png_new(vmon->vcr_backend, output);
+ png_dest = vcr_dest_png_new(vmon->vcr_backend, output, vmon->name, payload);
if (!png_dest) {
(void) unlink(vmon->strobe_file);
(void) fclose(output);
@@ -849,7 +849,7 @@ static int vmon_strobe(vmon_t *vmon)
}
-static int vmon_snapshot(vmon_t *vmon)
+static int vmon_snapshot(vmon_t *vmon, const char *payload)
{
#ifdef USE_PNG
time_t now, *t_ptr = &now;
@@ -905,7 +905,7 @@ static int vmon_snapshot(vmon_t *vmon)
{
vcr_dest_t *png_dest;
- png_dest = vcr_dest_png_new(vmon->vcr_backend, output);
+ png_dest = vcr_dest_png_new(vmon->vcr_backend, output, vmon->name, payload);
if (!png_dest) {
(void) unlink(tmp_path);
(void) fclose(output);
@@ -1037,7 +1037,7 @@ int main(int argc, const char * const *argv)
continue;
if (WIFEXITED(status) || WIFSIGNALED(status)) {
- if (vmon->snapshot && (r = vmon_snapshot(vmon)) < 0)
+ if (vmon->snapshot && (r = vmon_snapshot(vmon, NULL)) < 0)
VWM_ERROR("error saving snapshot: %s", strerror(-r));
ret = WEXITSTATUS(status);
@@ -1056,7 +1056,7 @@ int main(int argc, const char * const *argv)
if (got_sigusr2) {
int r;
- if ((r = vmon_strobe(vmon)) < 0)
+ if ((r = vmon_strobe(vmon, NULL)) < 0)
VWM_ERROR("error saving strobe file: %s", strerror(-r));
got_sigusr2 = 0;
@@ -1065,7 +1065,7 @@ int main(int argc, const char * const *argv)
if (got_sigusr1 || (vmon->snapshots_interval && !vmon->n_snapshots)) {
int r;
- if ((r = vmon_snapshot(vmon)) < 0)
+ if ((r = vmon_snapshot(vmon, NULL)) < 0)
VWM_ERROR("error saving snapshot: %s", strerror(-r));
got_sigusr1 = 0;
© All Rights Reserved