Discussion:
[PATCH 2/3] add long track format options
Johannes Weißl
2011-03-10 11:47:55 UTC
Permalink
e.g. %-20{artist} instead of %-20a

Suggested by Timo:
http://sourceforge.net/mailarchive/message.php?msg_id=1970124
---
format_print.c | 86 ++++++++++++++++++++++++++++++++++++++-----------------
format_print.h | 15 ++++++----
options.c | 2 +-
ui_curses.c | 53 +++++++++++++++++++---------------
ui_curses.h | 2 +
5 files changed, 100 insertions(+), 58 deletions(-)

diff --git a/format_print.c b/format_print.c
index 88c3a1f..3487d10 100644
--- a/format_print.c
+++ b/format_print.c
@@ -180,6 +180,11 @@ static void print_str(char *buf, int *idx, const char *str)
*idx = d;
}

+static inline int strnequal(const char *a, const char *b, size_t b_len)
+{
+ return a && (strlen(a) == b_len) && (memcmp(a, b, b_len) == 0);
+}
+
static void print(char *str, const char *format, const struct format_option *fopts)
{
/* format and str indices */
@@ -187,6 +192,8 @@ static void print(char *str, const char *format, const struct format_option *fop

while (format[s]) {
const struct format_option *fo;
+ int long_len = 0;
+ const char *long_begin = NULL;
uchar u;

u = u_get_char(format, &s);
@@ -220,8 +227,19 @@ static void print(char *str, const char *format, const struct format_option *fop
width += u - '0';
u = u_get_char(format, &s);
}
- for (fo = fopts; fo->ch; fo++) {
- if (fo->ch == u) {
+ if (u == '{') {
+ long_begin = format + s;
+ while (1) {
+ u = u_get_char(format, &s);
+ BUG_ON(u == 0);
+ if (u == '}')
+ break;
+ long_len++;
+ }
+ }
+ for (fo = fopts; fo->type; fo++) {
+ if (long_len ? strnequal(fo->str, long_begin, long_len)
+ : (fo->ch == u)) {
int type = fo->type;

if (fo->empty) {
@@ -259,7 +277,8 @@ int format_print(char *str, int str_width, const char *format, const struct form

while (format[s]) {
const struct format_option *fo;
- int nlen;
+ int nlen, long_len = 0;
+ const char *long_begin = NULL;
uchar u;

u = u_get_char(format, &s);
@@ -287,9 +306,20 @@ int format_print(char *str, int str_width, const char *format, const struct form
nlen += u - '0';
u = u_get_char(format, &s);
}
+ if (u == '{') {
+ long_begin = format + s;
+ while (1) {
+ u = u_get_char(format, &s);
+ BUG_ON(u == 0);
+ if (u == '}')
+ break;
+ long_len++;
+ }
+ }
for (fo = fopts; ; fo++) {
- BUG_ON(fo->ch == 0);
- if (fo->ch == u) {
+ BUG_ON(fo->type == 0);
+ if (long_len ? strnequal(fo->str, long_begin, long_len)
+ : (fo->ch == u)) {
int type = fo->type;
int l = 0;

@@ -397,8 +427,7 @@ int format_print(char *str, int str_width, const char *format, const struct form
return 0;
}

-/* FIXME: compare with struct format_option[] */
-int format_valid(const char *format)
+int format_valid(const char *format, const struct format_option *fopts)
{
int s = 0;

@@ -407,7 +436,9 @@ int format_valid(const char *format)

u = u_get_char(format, &s);
if (u == '%') {
- int pad_zero = 0;
+ int pad_zero = 0, long_len = 0;
+ const struct format_option *fo;
+ const char *long_begin = NULL;

u = u_get_char(format, &s);
if (u == '%' || u == '=')
@@ -420,26 +451,27 @@ int format_valid(const char *format)
}
while (isdigit(u))
u = u_get_char(format, &s);
- switch (u) {
- case 'A':
- case 'a':
- case 'l':
- case 't':
- case 'd':
- case 'g':
- case 'c':
- case 'f':
- case 'F':
- if (pad_zero)
- return 0;
- break;
- case 'D':
- case 'n':
- case 'y':
- break;
- default:
- return 0;
+ if (u == '{') {
+ long_begin = format + s;
+ while (1) {
+ u = u_get_char(format, &s);
+ if (!u)
+ return 0;
+ if (u == '}')
+ break;
+ long_len++;
+ }
+ }
+ for (fo = fopts; fo->type; fo++) {
+ if (long_len ? strnequal(fo->str, long_begin, long_len)
+ : (fo->ch == u)) {
+ if (pad_zero && !fo->pad_zero)
+ return 0;
+ break;
+ }
}
+ if (! fo->type)
+ return 0;
}
}
return 1;
diff --git a/format_print.h b/format_print.h
index 08db08b..fb73fad 100644
--- a/format_print.h
+++ b/format_print.h
@@ -11,8 +11,11 @@ struct format_option {
};
/* set to 1 if you want to disable printing */
unsigned int empty : 1;
- enum { FO_STR, FO_INT, FO_TIME } type;
+ /* set to 1 if zero padding is allowed */
+ unsigned int pad_zero : 1;
+ enum { FO_STR = 1, FO_INT, FO_TIME } type;
char ch;
+ const char *str;
};

/* gcc < 4.6 and icc < 12.0 can't properly initialize anonymous unions */
@@ -23,12 +26,12 @@ struct format_option {
#define UNION_INIT(f, v) .f = v
#endif

-#define DEF_FO_STR(c) { UNION_INIT(fo_str, NULL), .type = FO_STR, .ch = c }
-#define DEF_FO_INT(c) { UNION_INIT(fo_int, 0), .type = FO_INT, .ch = c }
-#define DEF_FO_TIME(c) { UNION_INIT(fo_time, 0), .type = FO_TIME, .ch = c }
-#define DEF_FO_END { UNION_INIT(fo_str, NULL), .type = 0, .ch = 0 }
+#define DEF_FO_STR(c, s, z) { UNION_INIT(fo_str, NULL), .type = FO_STR, .pad_zero = z, .ch = c, .str = s }
+#define DEF_FO_INT(c, s, z) { UNION_INIT(fo_int, 0), .type = FO_INT, .pad_zero = z, .ch = c, .str = s }
+#define DEF_FO_TIME(c, s, z) { UNION_INIT(fo_time, 0), .type = FO_TIME, .pad_zero = z, .ch = c, .str = s }
+#define DEF_FO_END { .type = 0 }

int format_print(char *str, int width, const char *format, const struct format_option *fopts);
-int format_valid(const char *format);
+int format_valid(const char *format, const struct format_option *fopts);

#endif
diff --git a/options.c b/options.c
index 0febb78..007a5b9 100644
--- a/options.c
+++ b/options.c
@@ -844,7 +844,7 @@ static void set_format(unsigned int id, const char *buf)
{
char **fmtp = id_to_fmt(id);

- if (!format_valid(buf)) {
+ if (!track_format_valid(buf)) {
error_msg("invalid format string");
return;
}
diff --git a/ui_curses.c b/ui_curses.c
index 0df5a03..c60d8a6 100644
--- a/ui_curses.c
+++ b/ui_curses.c
@@ -221,18 +221,18 @@ enum {
};

static struct format_option track_fopts[NR_TFS + 1] = {
- DEF_FO_STR('A'),
- DEF_FO_STR('a'),
- DEF_FO_STR('l'),
- DEF_FO_INT('D'),
- DEF_FO_INT('n'),
- DEF_FO_STR('t'),
- DEF_FO_STR('y'),
- DEF_FO_STR('g'),
- DEF_FO_STR('c'),
- DEF_FO_TIME('d'),
- DEF_FO_STR('f'),
- DEF_FO_STR('F'),
+ DEF_FO_STR('A', "albumartist", 0),
+ DEF_FO_STR('a', "artist", 0),
+ DEF_FO_STR('l', "album", 0),
+ DEF_FO_INT('D', "discnumber", 1),
+ DEF_FO_INT('n', "tracknumber", 1),
+ DEF_FO_STR('t', "title", 0),
+ DEF_FO_STR('y', "date", 1),
+ DEF_FO_STR('g', "genre", 0),
+ DEF_FO_STR('c', "comment", 0),
+ DEF_FO_TIME('d', "duration", 0),
+ DEF_FO_STR('f', "path", 0),
+ DEF_FO_STR('F', "filename", 0),
DEF_FO_END
};

@@ -253,21 +253,26 @@ enum {
};

static struct format_option status_fopts[NR_SFS + 1] = {
- DEF_FO_STR('s'),
- DEF_FO_TIME('p'),
- DEF_FO_TIME('d'),
- DEF_FO_TIME('t'),
- DEF_FO_INT('v'),
- DEF_FO_INT('l'),
- DEF_FO_INT('r'),
- DEF_FO_INT('b'),
- DEF_FO_STR('R'),
- DEF_FO_STR('C'),
- DEF_FO_STR('S'),
- DEF_FO_STR('L'),
+ DEF_FO_STR('s', NULL, 0),
+ DEF_FO_TIME('p', NULL, 0),
+ DEF_FO_TIME('d', NULL, 0),
+ DEF_FO_TIME('t', NULL, 0),
+ DEF_FO_INT('v', NULL, 0),
+ DEF_FO_INT('l', NULL, 0),
+ DEF_FO_INT('r', NULL, 0),
+ DEF_FO_INT('b', NULL, 0),
+ DEF_FO_STR('R', NULL, 0),
+ DEF_FO_STR('C', NULL, 0),
+ DEF_FO_STR('S', NULL, 0),
+ DEF_FO_STR('L', NULL, 0),
DEF_FO_END
};

+int track_format_valid(const char *format)
+{
+ return format_valid(format, track_fopts);
+}
+
static void utf8_encode(const char *buffer)
{
static iconv_t cd = (iconv_t)-1;
diff --git a/ui_curses.h b/ui_curses.h
index 70cf3ed..44b0ef5 100644
--- a/ui_curses.h
+++ b/ui_curses.h
@@ -61,4 +61,6 @@ void enter_command_mode(void);
void enter_search_mode(void);
void enter_search_backward_mode(void);

+int track_format_valid(const char *format);
+
#endif
--
1.7.4.1
Johannes Weißl
2011-03-10 11:47:56 UTC
Permalink
new sort keys:
rg_track_gain, rg_track_peak, rg_album_gain, rg_album_peak

new track format options:
%{rg_track_gain}, %{rg_track_peak}, %{rg_album_gain}, %{rg_album_peak}
---
comment.c | 20 ++++++++++++++++++++
comment.h | 1 +
format_print.c | 35 +++++++++++++++++++++++++++++++++++
format_print.h | 4 +++-
options.c | 4 ++++
player.c | 33 ++++++++++-----------------------
track_info.c | 21 +++++++++++++++++++++
track_info.h | 32 ++++++++++++++++++++------------
ui_curses.c | 20 ++++++++++++++++++++
9 files changed, 134 insertions(+), 36 deletions(-)

diff --git a/comment.c b/comment.c
index 71139fb..eab35e3 100644
--- a/comment.c
+++ b/comment.c
@@ -80,6 +80,26 @@ int comments_get_int(const struct keyval *comments, const char *key)
return ival;
}

+double comments_get_double(const struct keyval *comments, const char *key)
+{
+ const char *val;
+ char *end;
+ double d;
+
+ val = keyvals_get_val(comments, key);
+ if (!val || strcmp(val, "") == 0)
+ goto error;
+
+ d = strtod(val, &end);
+ if (val == end)
+ goto error;
+
+ return d;
+
+error:
+ return strtod("NAN", NULL);
+}
+
/* Return date as an integer in the form YYYYMMDD, for sorting purposes.
* This function is not year 10000 compliant. */
int comments_get_date(const struct keyval *comments, const char *key)
diff --git a/comment.h b/comment.h
index 635b7ee..18b67f3 100644
--- a/comment.h
+++ b/comment.h
@@ -10,6 +10,7 @@ const char *comments_get_albumartist(const struct keyval *comments);
const char *comments_get_artistsort(const struct keyval *comments); /* can return NULL */

int comments_get_int(const struct keyval *comments, const char *key);
+double comments_get_double(const struct keyval *comments, const char *key);
int comments_get_date(const struct keyval *comments, const char *key);

int comments_add(struct growing_keyvals *c, const char *key, char *val);
diff --git a/format_print.c b/format_print.c
index 3487d10..0fe2b53 100644
--- a/format_print.c
+++ b/format_print.c
@@ -3,6 +3,7 @@
#include "xmalloc.h"
#include "debug.h"

+#include <stdio.h>
#include <string.h>
#include <ctype.h>

@@ -73,6 +74,36 @@ static int print_num(char *buf, int num)
return stack_print(buf, stack, p);
}

+#define DBL_MAX_LEN (20)
+
+static int format_double(char *buf, int buflen, double num)
+{
+ int len = snprintf(buf, buflen, "%f", num);
+ /* skip trailing zeros */
+ while (len > 0 && buf[len-1] == '0')
+ len--;
+ return len;
+}
+
+static int double_len(double num)
+{
+ char buf[DBL_MAX_LEN];
+ return format_double(buf, DBL_MAX_LEN, num);
+}
+
+static int print_double(char *buf, double num)
+{
+ char stack[DBL_MAX_LEN], b[DBL_MAX_LEN];
+ int i, p = 0;
+
+ i = format_double(b, DBL_MAX_LEN, num) - 1;
+ while (i >= 0) {
+ stack[p++] = b[i];
+ i--;
+ }
+ return stack_print(buf, stack, p);
+}
+
/* print '{,-}{h:,}mm:ss' */
static int print_time(char *buf, int t)
{
@@ -251,6 +282,8 @@ static void print(char *str, const char *format, const struct format_option *fop
d += print_num(str + d, fo->fo_int);
} else if (type == FO_TIME) {
d += print_time(str + d, fo->fo_time);
+ } else if (type == FO_DOUBLE) {
+ d += print_double(str + d, fo->fo_double);
}
break;
}
@@ -341,6 +374,8 @@ int format_print(char *str, int str_width, const char *format, const struct form
} else {
l += 5;
}
+ } else if (type == FO_DOUBLE) {
+ l = double_len(fo->fo_double);
}
if (nlen) {
*len += nlen;
diff --git a/format_print.h b/format_print.h
index fb73fad..67b4e58 100644
--- a/format_print.h
+++ b/format_print.h
@@ -8,12 +8,13 @@ struct format_option {
int fo_int;
/* [h:]mm:ss. can be negative */
int fo_time;
+ double fo_double;
};
/* set to 1 if you want to disable printing */
unsigned int empty : 1;
/* set to 1 if zero padding is allowed */
unsigned int pad_zero : 1;
- enum { FO_STR = 1, FO_INT, FO_TIME } type;
+ enum { FO_STR = 1, FO_INT, FO_TIME, FO_DOUBLE } type;
char ch;
const char *str;
};
@@ -29,6 +30,7 @@ struct format_option {
#define DEF_FO_STR(c, s, z) { UNION_INIT(fo_str, NULL), .type = FO_STR, .pad_zero = z, .ch = c, .str = s }
#define DEF_FO_INT(c, s, z) { UNION_INIT(fo_int, 0), .type = FO_INT, .pad_zero = z, .ch = c, .str = s }
#define DEF_FO_TIME(c, s, z) { UNION_INIT(fo_time, 0), .type = FO_TIME, .pad_zero = z, .ch = c, .str = s }
+#define DEF_FO_DOUBLE(c, s, z) { UNION_INIT(fo_double, 0.), .type = FO_DOUBLE, .pad_zero = z, .ch = c, .str = s }
#define DEF_FO_END { .type = 0 }

int format_print(char *str, int width, const char *format, const struct format_option *fopts);
diff --git a/options.c b/options.c
index 007a5b9..f519142 100644
--- a/options.c
+++ b/options.c
@@ -201,6 +201,10 @@ static const struct {
{ "albumartist", SORT_ALBUMARTIST },
{ "filename", SORT_FILENAME },
{ "filemtime", SORT_FILEMTIME },
+ { "rg_track_gain", SORT_RG_TRACK_GAIN },
+ { "rg_track_peak", SORT_RG_TRACK_PEAK },
+ { "rg_album_gain", SORT_RG_ALBUM_GAIN },
+ { "rg_album_peak", SORT_RG_ALBUM_PEAK },
{ NULL, SORT_INVALID }
};

diff --git a/player.c b/player.c
index 9b97969..4770725 100644
--- a/player.c
+++ b/player.c
@@ -249,17 +249,8 @@ static void scale_samples(char *buffer, unsigned int *countp)
}
}

-static int parse_double(const char *str, double *val)
-{
- char *end;
-
- *val = strtod(str, &end);
- return str == end;
-}
-
static void update_rg_scale(void)
{
- const char *g, *p;
double gain, peak, db, scale, limit;

replaygain_scale = 1.0;
@@ -267,31 +258,27 @@ static void update_rg_scale(void)
return;

if (replaygain == RG_TRACK || replaygain == RG_TRACK_PREFERRED) {
- g = keyvals_get_val(player_info.ti->comments, "replaygain_track_gain");
- p = keyvals_get_val(player_info.ti->comments, "replaygain_track_peak");
+ gain = player_info.ti->rg_track_gain;
+ peak = player_info.ti->rg_track_peak;
} else {
- g = keyvals_get_val(player_info.ti->comments, "replaygain_album_gain");
- p = keyvals_get_val(player_info.ti->comments, "replaygain_album_peak");
+ gain = player_info.ti->rg_album_gain;
+ peak = player_info.ti->rg_album_peak;
}

- if (!g || !p) {
+ if (isnan(gain) || isnan(peak)) {
if (replaygain == RG_TRACK_PREFERRED) {
- g = keyvals_get_val(player_info.ti->comments, "replaygain_album_gain");
- p = keyvals_get_val(player_info.ti->comments, "replaygain_album_peak");
+ gain = player_info.ti->rg_album_gain;
+ peak = player_info.ti->rg_album_peak;
} else if (replaygain == RG_ALBUM_PREFERRED) {
- g = keyvals_get_val(player_info.ti->comments, "replaygain_track_gain");
- p = keyvals_get_val(player_info.ti->comments, "replaygain_track_peak");
+ gain = player_info.ti->rg_track_gain;
+ peak = player_info.ti->rg_track_peak;
}
}

- if (!g || !p) {
+ if (isnan(gain) || isnan(peak)) {
d_print("gain or peak not available\n");
return;
}
- if (parse_double(g, &gain) || parse_double(p, &peak)) {
- d_print("could not parse gain (%s) or peak (%s)\n", g, p);
- return;
- }
if (peak < 0.05) {
d_print("peak (%g) is too small\n", peak);
return;
diff --git a/track_info.c b/track_info.c
index 3c49c3a..17ba9d4 100644
--- a/track_info.c
+++ b/track_info.c
@@ -27,6 +27,7 @@
#include "debug.h"

#include <string.h>
+#include <math.h>

static void track_info_free(struct track_info *ti)
{
@@ -65,6 +66,11 @@ void track_info_set_comments(struct track_info *ti, struct keyval *comments) {
ti->artistsort = comments_get_artistsort(comments);
ti->is_va_compilation = track_is_va_compilation(comments);

+ ti->rg_track_gain = comments_get_double(comments, "replaygain_track_gain");
+ ti->rg_track_peak = comments_get_double(comments, "replaygain_track_peak");
+ ti->rg_album_gain = comments_get_double(comments, "replaygain_album_gain");
+ ti->rg_album_peak = comments_get_double(comments, "replaygain_album_peak");
+
ti->collkey_artist = u_strcasecoll_key0(ti->artist);
ti->collkey_album = u_strcasecoll_key0(ti->album);
ti->collkey_title = u_strcasecoll_key0(ti->title);
@@ -150,6 +156,15 @@ int track_info_matches(const struct track_info *ti, const char *text, unsigned i
return track_info_matches_full(ti, text, flags, 0, 1);
}

+static int doublecmp0(double a, double b)
+{
+ if (isnan(a))
+ return isnan(b) ? 0 : -1;
+ if (isnan(b))
+ return 1;
+ return (int) (a - b);
+}
+
/* this function gets called *alot*, it must be very fast */
int track_info_cmp(const struct track_info *a, const struct track_info *b, const sort_key_t *keys)
{
@@ -172,6 +187,12 @@ int track_info_cmp(const struct track_info *a, const struct track_info *b, const
/* NOTE: filenames are not necessarily UTF-8 */
res = strcoll(a->filename, b->filename);
break;
+ case SORT_RG_TRACK_GAIN:
+ case SORT_RG_TRACK_PEAK:
+ case SORT_RG_ALBUM_GAIN:
+ case SORT_RG_ALBUM_PEAK:
+ res = doublecmp0(getentry(a, key, double), getentry(b, key, double));
+ break;
default:
av = getentry(a, key, const char *);
bv = getentry(b, key, const char *);
diff --git a/track_info.h b/track_info.h
index a87fe08..814434f 100644
--- a/track_info.h
+++ b/track_info.h
@@ -37,6 +37,10 @@ struct track_info {
int tracknumber;
int discnumber;
int date;
+ double rg_track_gain;
+ double rg_track_peak;
+ double rg_album_gain;
+ double rg_album_peak;
const char *artist;
const char *album;
const char *title;
@@ -57,18 +61,22 @@ struct track_info {

typedef size_t sort_key_t;

-#define SORT_ARTIST offsetof(struct track_info, collkey_artist)
-#define SORT_ALBUM offsetof(struct track_info, collkey_album)
-#define SORT_TITLE offsetof(struct track_info, collkey_title)
-#define SORT_TRACKNUMBER offsetof(struct track_info, tracknumber)
-#define SORT_DISCNUMBER offsetof(struct track_info, discnumber)
-#define SORT_DATE offsetof(struct track_info, date)
-#define SORT_GENRE offsetof(struct track_info, collkey_genre)
-#define SORT_COMMENT offsetof(struct track_info, collkey_comment)
-#define SORT_ALBUMARTIST offsetof(struct track_info, collkey_albumartist)
-#define SORT_FILENAME offsetof(struct track_info, filename)
-#define SORT_FILEMTIME offsetof(struct track_info, mtime)
-#define SORT_INVALID ((sort_key_t) (-1))
+#define SORT_ARTIST offsetof(struct track_info, collkey_artist)
+#define SORT_ALBUM offsetof(struct track_info, collkey_album)
+#define SORT_TITLE offsetof(struct track_info, collkey_title)
+#define SORT_TRACKNUMBER offsetof(struct track_info, tracknumber)
+#define SORT_DISCNUMBER offsetof(struct track_info, discnumber)
+#define SORT_DATE offsetof(struct track_info, date)
+#define SORT_RG_TRACK_GAIN offsetof(struct track_info, rg_track_gain)
+#define SORT_RG_TRACK_PEAK offsetof(struct track_info, rg_track_peak)
+#define SORT_RG_ALBUM_GAIN offsetof(struct track_info, rg_album_gain)
+#define SORT_RG_ALBUM_PEAK offsetof(struct track_info, rg_album_peak)
+#define SORT_GENRE offsetof(struct track_info, collkey_genre)
+#define SORT_COMMENT offsetof(struct track_info, collkey_comment)
+#define SORT_ALBUMARTIST offsetof(struct track_info, collkey_albumartist)
+#define SORT_FILENAME offsetof(struct track_info, filename)
+#define SORT_FILEMTIME offsetof(struct track_info, mtime)
+#define SORT_INVALID ((sort_key_t) (-1))

#define TI_MATCH_ARTIST (1 << 0)
#define TI_MATCH_ALBUM (1 << 1)
diff --git a/ui_curses.c b/ui_curses.c
index c60d8a6..90cb13a 100644
--- a/ui_curses.c
+++ b/ui_curses.c
@@ -60,6 +60,7 @@
#include <iconv.h>
#include <signal.h>
#include <stdarg.h>
+#include <math.h>

#if defined(__sun__) || defined(__CYGWIN__)
/* TIOCGWINSZ */
@@ -217,6 +218,10 @@ enum {
TF_DURATION,
TF_PATHFILE,
TF_FILE,
+ TF_RG_TRACK_GAIN,
+ TF_RG_TRACK_PEAK,
+ TF_RG_ALBUM_GAIN,
+ TF_RG_ALBUM_PEAK,
NR_TFS
};

@@ -233,6 +238,10 @@ static struct format_option track_fopts[NR_TFS + 1] = {
DEF_FO_TIME('d', "duration", 0),
DEF_FO_STR('f', "path", 0),
DEF_FO_STR('F', "filename", 0),
+ DEF_FO_DOUBLE('\0', "rg_track_gain", 0),
+ DEF_FO_DOUBLE('\0', "rg_track_peak", 0),
+ DEF_FO_DOUBLE('\0', "rg_album_gain", 0),
+ DEF_FO_DOUBLE('\0', "rg_album_peak", 0),
DEF_FO_END
};

@@ -485,6 +494,13 @@ static inline void fopt_set_int(struct format_option *fopt, int value, int empty
fopt->empty = empty;
}

+static inline void fopt_set_double(struct format_option *fopt, double value, int empty)
+{
+ BUG_ON(fopt->type != FO_DOUBLE);
+ fopt->fo_double = value;
+ fopt->empty = empty;
+}
+
static inline void fopt_set_time(struct format_option *fopt, int value, int empty)
{
BUG_ON(fopt->type != FO_TIME);
@@ -513,6 +529,10 @@ static void fill_track_fopts_track_info(struct track_info *info)
fopt_set_str(&track_fopts[TF_GENRE], info->genre);
fopt_set_str(&track_fopts[TF_COMMENT], info->comment);
fopt_set_time(&track_fopts[TF_DURATION], info->duration, info->duration == -1);
+ fopt_set_double(&track_fopts[TF_RG_TRACK_GAIN], info->rg_track_gain, isnan(info->rg_track_gain));
+ fopt_set_double(&track_fopts[TF_RG_TRACK_PEAK], info->rg_track_peak, isnan(info->rg_track_peak));
+ fopt_set_double(&track_fopts[TF_RG_ALBUM_GAIN], info->rg_album_gain, isnan(info->rg_album_gain));
+ fopt_set_double(&track_fopts[TF_RG_ALBUM_PEAK], info->rg_album_peak, isnan(info->rg_album_peak));
fopt_set_str(&track_fopts[TF_PATHFILE], filename);
if (is_url(info->filename)) {
fopt_set_str(&track_fopts[TF_FILE], filename);
--
1.7.4.1
Johannes Weißl
2011-03-10 13:58:57 UTC
Permalink
---
Doc/cmus.txt | 49 ++++++++++++++++++++++---------------------------
1 files changed, 22 insertions(+), 27 deletions(-)

diff --git a/Doc/cmus.txt b/Doc/cmus.txt
index 4ebf9be..7e84694 100644
--- a/Doc/cmus.txt
+++ b/Doc/cmus.txt
@@ -937,32 +937,24 @@ views.

NOTE: *altformat_\** options are used when there are no tags available.

-Special Characters:
-
- %a
- artist
- %A
- album artist
- %l
- album
- %D
- disc number
- %n
- track number
- %t
- title
- %g
- genre
- %c
- comment
- %y
- year
- %d
- duration
- %f
- path and filename
- %F
- filename
+Special Keys:
+
+ %a %{artist} @br
+ %A %{albumartist} @br
+ %l %{album} @br
+ %D %{discnumber} @br
+ %n %{tracknumber} @br
+ %t %{title} @br
+ %g %{genre} @br
+ %c %{comment} @br
+ %y %{date} @br
+ %d %{duration} @br
+ %f %{path} @br
+ %F %{filename} @br
+ %{rg_track_gain} @br
+ %{rg_track_peak} @br
+ %{rg_album_gain} @br
+ %{rg_album_peak} @br
%=
start align right (use at most once)
%%
@@ -976,6 +968,7 @@ Examples:
@pre
:set format_trackwin= %02n. %t (%y)%= %d
:set format_current= %n. %-30t %40F (%y)%= %d
+ :set format_playlist= %f%= %6{rg_track_gain} dB %8{rg_track_peak}
@endpre

@h2 Sort Keys
@@ -983,7 +976,9 @@ Examples:
Sort option (lib_sort, pl_sort) value is space separated list of the following
sort keys:

- artist, album, title, tracknumber, discnumber, date, genre, comment, filename, filemtime
+ artist, album, title, tracknumber, discnumber, date, genre, comment,
+ albumartist, filename, filemtime, rg_track_gain, rg_track_peak,
+ rg_album_gain, rg_album_peak


@h1 PLUGIN OPTIONS
--
1.7.4.1
Gregory Petrosyan
2011-03-10 23:00:37 UTC
Permalink
Post by Johannes Weißl
e.g. %-20{artist} instead of %-20a
http://sourceforge.net/mailarchive/message.php?msg_id=1970124
Thanks Johannes, in -pu now (although I've not reviewed the patches yet)!

I remember at some time you said you have patches for %{bitrate} etc.
Is this correct? If so, do you plan to post them as well (I hope yes
:-) ?

                Gregory
Johannes Weißl
2011-03-15 23:09:28 UTC
Permalink
For people who use cmus on terminals with different COLUMNS sizes,
static format width is suboptimal. This patch introduces percentages,
e.g.:

old:
%-20a %3n. %t%= %y %d

new:
%-25%a %3n. %t%= %y %d

This change is fully backwards compatible.
---
Doc/cmus.txt | 7 +++++--
format_print.c | 16 +++++++++++++---
2 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/Doc/cmus.txt b/Doc/cmus.txt
index 7e84694..83a0b78 100644
--- a/Doc/cmus.txt
+++ b/Doc/cmus.txt
@@ -960,8 +960,10 @@ Special Keys:
%%
literal *%*

-You can use printf style formatting (width, alignment, padding). To see
-current value of an option type *:set option=<TAB>*.
+You can use printf style formatting (width, alignment, padding). As an
+extension, the width can have a %-suffix, to specify a percentage of the
+terminal width. @br
+To see current value of an option type *:set option=<TAB>*.

Examples:

@@ -969,6 +971,7 @@ Examples:
:set format_trackwin= %02n. %t (%y)%= %d
:set format_current= %n. %-30t %40F (%y)%= %d
:set format_playlist= %f%= %6{rg_track_gain} dB %8{rg_track_peak}
+ :set format_playlist= %-25%a %-15%l %3n. %t%= %y %d
@endpre

@h2 Sort Keys
diff --git a/format_print.c b/format_print.c
index 0fe2b53..6ca0562 100644
--- a/format_print.c
+++ b/format_print.c
@@ -216,7 +216,7 @@ static inline int strnequal(const char *a, const char *b, size_t b_len)
return a && (strlen(a) == b_len) && (memcmp(a, b, b_len) == 0);
}

-static void print(char *str, const char *format, const struct format_option *fopts)
+static void print(char *str, int str_width, const char *format, const struct format_option *fopts)
{
/* format and str indices */
int s = 0, d = 0;
@@ -258,6 +258,10 @@ static void print(char *str, const char *format, const struct format_option *fop
width += u - '0';
u = u_get_char(format, &s);
}
+ if (u == '%') {
+ width = (width * str_width) / 100.0 + 0.5;
+ u = u_get_char(format, &s);
+ }
if (u == '{') {
long_begin = format + s;
while (1) {
@@ -339,6 +343,10 @@ int format_print(char *str, int str_width, const char *format, const struct form
nlen += u - '0';
u = u_get_char(format, &s);
}
+ if (u == '%') {
+ nlen = (nlen * str_width) / 100.0 + 0.5;
+ u = u_get_char(format, &s);
+ }
if (u == '{') {
long_begin = format + s;
while (1) {
@@ -407,7 +415,7 @@ int format_print(char *str, int str_width, const char *format, const struct form
r_str[0] = 0;

if (lsize > 0) {
- print(l_str, format, fopts);
+ print(l_str, str_width, format, fopts);
#if DEBUG > 1
{
int ul = u_str_width(l_str);
@@ -417,7 +425,7 @@ int format_print(char *str, int str_width, const char *format, const struct form
#endif
}
if (rsize > 0) {
- print(r_str, format + eq_pos + 1, fopts);
+ print(r_str, str_width, format + eq_pos + 1, fopts);
#if DEBUG > 1
{
int ul = u_str_width(r_str);
@@ -486,6 +494,8 @@ int format_valid(const char *format, const struct format_option *fopts)
}
while (isdigit(u))
u = u_get_char(format, &s);
+ if (u == '%')
+ u = u_get_char(format, &s);
if (u == '{') {
long_begin = format + s;
while (1) {
--
1.7.4.1
Johannes Weißl
2011-03-18 01:50:54 UTC
Permalink
25% of a default 80-columns terminal are 20, so nothing changes there.
For broader (and narrower!) terminals this default is much nicer.
---
options.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/options.c b/options.c
index f519142..f7b8e62 100644
--- a/options.c
+++ b/options.c
@@ -935,8 +935,8 @@ static const struct {
{ "altformat_title", "%f" },
{ "altformat_trackwin", " %f%= %d " },
{ "format_current", " %a - %l -%3n. %t%= %y " },
- { "format_playlist", " %-20a %3n. %t%= %y %d " },
- { "format_playlist_va", " %-20A %3n. %t (%a)%= %y %d " },
+ { "format_playlist", " %-25%a %3n. %t%= %y %d " },
+ { "format_playlist_va", " %-25%A %3n. %t (%a)%= %y %d " },
{ "format_title", "%a - %l - %t (%y)" },
{ "format_trackwin", "%3n. %t%= %y %d " },
{ "format_trackwin_va", "%3n. %t (%a)%= %y %d " },
--
1.7.4.1
Gregory Petrosyan
2011-03-29 18:22:33 UTC
Permalink
FYI — merged all the longformat-related stuff, except for bitrate/format, to
master. Thanks!

Gregory

Loading...