From 8d611a325b3f01f34957876b2d9a1e1452086065 Mon Sep 17 00:00:00 2001 From: Marc Schoolderman Date: Mon, 5 Jun 2017 18:01:27 +0200 Subject: [PATCH] add support for POPM frames (see issue #9) --- CHANGES | 2 ++ getid3v2.cpp | 17 +++++++++++++---- getid3v2.h | 6 ++++-- id3.man | 3 ++- setid3v2.cpp | 9 ++++++++- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index 80f2e67..27c439e 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,8 @@ Changelog for 'id3'. 2017-156 (W23): id3-imges.c: prefix filenames of extract images with the path of the mp3 file they orginated from ("file.mp3:cover.jp3") + [gs]etid3v2.h: add support for POPM frames; referenced as POPM:email, + using the syntax [:playcounter] 2017-121 (W18): fileexp.cpp: [bugfix] files with [] in them were not being found diff --git a/getid3v2.cpp b/getid3v2.cpp index e57a062..02784ce 100644 --- a/getid3v2.cpp +++ b/getid3v2.cpp @@ -144,11 +144,20 @@ extern ID3v2::value_string tag::unbinarize(ID3FRAME f, charset::conv<>& descript return ID3v2::value_string(cs(""),0); if(ID3v2::is_counter(field)) { + const char* data = f->data; + if(ID3v2::has_desc(field)) { + if(!(data = membrk0(data, f->size, 0))) return conv<>(); + descriptor = conv(":") += conv(f->data, data - f->data); + data += 2; // data[-1] points to rating + } char buf[12]; // enough for 32bits unsigned long t = 0; - for(size_t n = 0; n < f->size; ++n) - t = t << 8 | (f->data[n] & 0xFF); - sprintf(buf, "%lu", t & 0xFFFFFFFFul); + for(size_t n = 0; n < f->size - (data - f->data); ++n) + t = t << 8 | (data[n] & 0xFF); + if(ID3v2::has_desc(field)) { + sprintf(buf, "%u:%lu", data[-1]&0xFFu, t & 0xFFFFFFFFul); + } else + sprintf(buf, "%lu", t & 0xFFFFFFFFul); return conv(buf); } @@ -160,7 +169,7 @@ extern ID3v2::value_string tag::unbinarize(ID3FRAME f, charset::conv<>& descript p += 3; // skip-ignore language field } if(ID3v2::has_desc(field)) { - const char *q = membrk0(p, f->size - (p - f->data), wide); + const char* q = membrk0(p, f->size - (p - f->data), wide); if(!q) return conv<>(); // malformed frame descriptor = conv(":"); switch(*f->data) { diff --git a/getid3v2.h b/getid3v2.h index 1cd1517..ffccd0a 100644 --- a/getid3v2.h +++ b/getid3v2.h @@ -44,10 +44,12 @@ namespace tag { { return field == "TXXX" || field == "TXX" || field == "WXXX" || field == "WXX" || field == "COMM" || field == "COM" || - field == "USLT" || field == "ULT"; } + field == "USLT" || field == "ULT" || + field == "POPM" || field == "POP"; } static bool is_counter(const std::string field) - { return field == "PCNT" || field == "CNT"; } + { return field == "PCNT" || field == "CNT" || + field == "POPM" || field == "POP"; } static bool is_url(const std::string field) { return field[0] == 'W'; } diff --git a/id3.man b/id3.man index 9739c3b..2633f95 100644 --- a/id3.man +++ b/id3.man @@ -390,7 +390,8 @@ W??/W??? (links), COM/COMM (comment), IPL/IPLS (involved people), ULT/USLT (lyrics), -CNT/PCNT (numeric play counter) and +CNT/PCNT (numeric play counter), +POP/POPM (popularimeter) and USER (tos, v2.3 only). Attempts to write ID3v2.2 frames to ID3v2.3 or vice versa will be ignored. diff --git a/setid3v2.cpp b/setid3v2.cpp index 400ecdb..a1065c8 100644 --- a/setid3v2.cpp +++ b/setid3v2.cpp @@ -178,7 +178,14 @@ static const string binarize(string field, charset::conv conten if(!ID3v2::is_valid(field)) return data; if(ID3v2::is_counter(field)) { - unsigned long t = strtoul(string(content).c_str(), 0, 0); + string s = content; + unsigned long t = strtoul(s.c_str(), 0, 0); + if(ID3v2::has_desc(field)) { + data.append(encode(0,descr)); + data.push_back(t&0xFFu); + string::size_type i = s.find(':'); + t = i==string::npos? 0 : strtoul(s.substr(i+1).c_str(), 0, 0); + } data.push_back(t >> 24 & 0xFF); data.push_back(t >> 16 & 0xFF); data.push_back(t >> 8 & 0xFF);