From a3227cadb5c6dde27f8d1ad187e319ea0b2fc21e Mon Sep 17 00:00:00 2001 From: Marcin Bukat Date: Wed, 7 Oct 2026 11:51:07 +0200 Subject: [PATCH] skin_engine: more tags for the recording screen What the built-in recording screen shows and the skin tags did not: - %RS size of the current recording, as "1.5MB" - %RP seconds in the pre-record buffer, empty unless pre-recording - %Rc clips counted by the peak meter - %Rt trigger state by name; as a conditional off, ready, steady, go, postrec, retrig, continue - %Rw recording warnings in hex, empty while there are none - %Ri recording source by name; as a conditional the same on every target: mic, line in, digital, FM radio - %Rg gain of the source in dB, the left channel's for line in and FM The manual gets a Recording section covering these and the recording tags that were there, none of which it described. Co-Authored-By: Claude Opus 5.5 Change-Id: I889f95fd472c472c2589393a6c77eff4a4fd5c8f --- apps/gui/skin_engine/skin_tokens.c | 100 +++++++++++++++++++++++++++++ lib/skin_parser/tag_table.c | 7 ++ lib/skin_parser/tag_table.h | 7 ++ manual/appendix/wps_tags.tex | 33 ++++++++++ 4 files changed, 147 insertions(+) diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c index c215ca4046..50faaa7ec1 100644 --- a/apps/gui/skin_engine/skin_tokens.c +++ b/apps/gui/skin_engine/skin_tokens.c @@ -1917,6 +1917,106 @@ const char *get_token_value(struct gui_wps *gwps, goto gtv_ret_numeric_tag_info; } + /* bytes recorded to the current file, as "1.5MB" */ + case SKIN_TOKEN_REC_SIZE: + return output_dyn_value(buf, buf_size, audio_num_recorded_bytes(), + byte_units, 4, true); + + /* seconds in the pre-record buffer; nothing unless pre-recording */ + case SKIN_TOKEN_REC_PRERECORD: + if (!(audio_status() & AUDIO_STATUS_PRERECORD)) + return NULL; + numeric_ret = audio_prerecorded_time() / HZ; + itoa_buf(buf, buf_size, numeric_ret); + numeric_buf = buf; + goto gtv_ret_numeric_tag_info; + + case SKIN_TOKEN_REC_CLIPCOUNT: + numeric_ret = pm_get_clipcount(); + itoa_buf(buf, buf_size, numeric_ret); + numeric_buf = buf; + goto gtv_ret_numeric_tag_info; + + /* trigger state; as a conditional: off, ready, steady, go, + * post-record, retrigger, continue */ + case SKIN_TOKEN_REC_TRIGGER: + { + static const char * const trig_name[] = + { "off", "ready", "steady", "go", "postrec", "retrig", + "continue" }; + int trig = peak_meter_trigger_status(); + + if (trig < 0 || trig >= (int)ARRAYLEN(trig_name)) + return NULL; + numeric_ret = trig + 1; + numeric_buf = (char *)trig_name[trig]; + goto gtv_ret_numeric_tag_info; + } + + /* recording warnings, in hex; nothing while there are none */ + case SKIN_TOKEN_REC_WARNING: + if (!(audio_status() & AUDIO_STATUS_WARNING)) + return NULL; + snprintf(buf, buf_size, "%08lX", + (unsigned long)pcm_rec_get_warnings()); + return buf; + + /* input source; as a conditional, the same on every target: mic, + * line in, digital, FM radio */ + case SKIN_TOKEN_REC_SOURCE: + switch (global_settings.rec_source) + { +#ifdef HAVE_MIC_REC + case AUDIO_SRC_MIC: + numeric_ret = 1; + numeric_buf = (char *)str(LANG_RECORDING_SRC_MIC); + break; +#endif +#ifdef HAVE_LINE_REC + case AUDIO_SRC_LINEIN: + numeric_ret = 2; + numeric_buf = (char *)str(LANG_LINE_IN); + break; +#endif +#ifdef HAVE_SPDIF_REC + case AUDIO_SRC_SPDIF: + numeric_ret = 3; + numeric_buf = (char *)str(LANG_RECORDING_SRC_DIGITAL); + break; +#endif +#ifdef HAVE_FMRADIO_REC + case AUDIO_SRC_FMRADIO: + numeric_ret = 4; + numeric_buf = (char *)str(LANG_FM_RADIO); + break; +#endif + default: + return NULL; + } + goto gtv_ret_numeric_tag_info; + + /* gain of the current source in dB - the left channel's for line + * in and FM radio; nothing for a source without one */ + case SKIN_TOKEN_REC_GAIN: + switch (global_settings.rec_source) + { +#ifdef HAVE_MIC_REC + case AUDIO_SRC_MIC: + format_sound_value_ex(buf, buf_size, SOUND_MIC_GAIN, + global_settings.rec_mic_gain, true); + return buf; +#endif +#if defined(HAVE_LINE_REC) || defined(HAVE_FMRADIO_REC) + HAVE_LINE_REC_(case AUDIO_SRC_LINEIN:) + HAVE_FMRADIO_REC_(case AUDIO_SRC_FMRADIO:) + format_sound_value_ex(buf, buf_size, SOUND_LEFT_GAIN, + global_settings.rec_left_gain, true); + return buf; +#endif + default: + return NULL; + } + #endif /* HAVE_RECORDING */ case SKIN_TOKEN_CURRENT_SCREEN: diff --git a/lib/skin_parser/tag_table.c b/lib/skin_parser/tag_table.c index a13e58a316..2e74c440b3 100644 --- a/lib/skin_parser/tag_table.c +++ b/lib/skin_parser/tag_table.c @@ -252,6 +252,13 @@ static const struct tag_info legal_tags[] = TAG(SKIN_TOKEN_REC_SECONDS, "Rs" , "", SKIN_REFRESH_DYNAMIC), TAG(SKIN_TOKEN_REC_MINUTES, "Rn" , "", SKIN_REFRESH_DYNAMIC), TAG(SKIN_TOKEN_REC_HOURS, "Rh" , "", SKIN_REFRESH_DYNAMIC), + TAG(SKIN_TOKEN_REC_SIZE, "RS" , "", SKIN_REFRESH_DYNAMIC), + TAG(SKIN_TOKEN_REC_PRERECORD, "RP" , "", SKIN_REFRESH_DYNAMIC), + TAG(SKIN_TOKEN_REC_CLIPCOUNT, "Rc" , "", SKIN_REFRESH_DYNAMIC), + TAG(SKIN_TOKEN_REC_TRIGGER, "Rt" , "", SKIN_REFRESH_DYNAMIC), + TAG(SKIN_TOKEN_REC_WARNING, "Rw" , "", SKIN_REFRESH_DYNAMIC), + TAG(SKIN_TOKEN_REC_SOURCE, "Ri" , "", SKIN_REFRESH_DYNAMIC), + TAG(SKIN_TOKEN_REC_GAIN, "Rg" , "", SKIN_REFRESH_DYNAMIC), /* Skin variables */ TAG(SKIN_TOKEN_VAR_SET, "vs", "SSi|I", SKIN_REFRESH_DYNAMIC), diff --git a/lib/skin_parser/tag_table.h b/lib/skin_parser/tag_table.h index eb2d409487..92647c1bdd 100644 --- a/lib/skin_parser/tag_table.h +++ b/lib/skin_parser/tag_table.h @@ -276,6 +276,13 @@ enum skin_token_type { SKIN_TOKEN_REC_SECONDS, SKIN_TOKEN_REC_MINUTES, SKIN_TOKEN_REC_HOURS, + SKIN_TOKEN_REC_SIZE, + SKIN_TOKEN_REC_PRERECORD, + SKIN_TOKEN_REC_CLIPCOUNT, + SKIN_TOKEN_REC_TRIGGER, + SKIN_TOKEN_REC_WARNING, + SKIN_TOKEN_REC_SOURCE, + SKIN_TOKEN_REC_GAIN, /* Radio Tokens */ diff --git a/manual/appendix/wps_tags.tex b/manual/appendix/wps_tags.tex index 121bb7a0cf..ad56890652 100644 --- a/manual/appendix/wps_tags.tex +++ b/manual/appendix/wps_tags.tex @@ -515,6 +515,39 @@ Examples: For general information where to put album art see \reference{ref:album_art}. } +\opt{recording}{ +\section{Recording} +These tags show the state of recording, in any skin. + \begin{tagmap} + \config{\%Rp} & Can this \dap{} record?\\ + \config{\%Rr} & Is a recording in progress?\\ + \config{\%Rh} & Hours of the current recording.\\ + \config{\%Rn} & Minutes of the current recording, 00 to 59.\\ + \config{\%Rs} & Seconds of the current recording, 00 to 59.\\ + \config{\%RS} & Size of the current recording, e.g. ``1.5MB''.\\ + \config{\%RP} & Seconds in the pre-record buffer; empty unless + pre-recording.\\ + \config{\%Re} & Recording format: wav, aiff, wv or mp3. As a conditional: + \config{\%?Re}.\\ + \config{\%Rf} & Sample rate in kHz, e.g. ``44.1''. As a conditional, 1 to + 12: 96, 88.2, 64, 48, 44.1, 32, 24, 22.05, 16, 12, 11.025 and 8~kHz.\\ + \config{\%Rb} & MP3 bitrate in kbps; empty for the other formats. As a + conditional, 1 to 18 for 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, + 144, 160, 192, 224, 256 and 320~kbps.\\ + \config{\%Rm} & Is the recording mono?\\ + \config{\%Ri} & Recording source, by name. As a conditional, the same on + every \dap{}: \config{\%?Ri}.\\ + \config{\%Rg} & Gain of the recording source in dB -- for line in and + FM radio the left channel's. Empty for a source without a gain.\\ + \config{\%Rc} & Number of clips the peak meter has counted.\\ + \config{\%Rt} & Trigger state: off, ready, steady, go, postrec, retrig or + continue. As a conditional: + \config{\%?Rt}.\\ + \config{\%Rw} & Recording warnings, as a hexadecimal number; empty while + there are none.\\ + \end{tagmap} +} + \opt{radio}{ \section{FM Radio} \begin{tagmap}