summaryrefslogtreecommitdiff
path: root/firmware/replaygain.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/replaygain.c')
-rw-r--r--firmware/replaygain.c108
1 files changed, 107 insertions, 1 deletions
diff --git a/firmware/replaygain.c b/firmware/replaygain.c
index 23a25cc310..542eee6101 100644
--- a/firmware/replaygain.c
+++ b/firmware/replaygain.c
@@ -20,9 +20,12 @@
20#include <ctype.h> 20#include <ctype.h>
21#include <inttypes.h> 21#include <inttypes.h>
22#include <math.h> 22#include <math.h>
23#include <stdbool.h>
23#include <stdio.h> 24#include <stdio.h>
24#include <stdlib.h> 25#include <stdlib.h>
25#include <stdbool.h> 26#include <string.h>
27#include <system.h>
28#include "id3.h"
26#include "debug.h" 29#include "debug.h"
27 30
28/* The fixed point math routines (with the exception of fp_atof) are based 31/* The fixed point math routines (with the exception of fp_atof) are based
@@ -326,3 +329,106 @@ long get_replaypeak(const char* str)
326 329
327 return peak; 330 return peak;
328} 331}
332
333/* Compare two strings, ignoring case, up to the end nil or another end of
334 * string character. E.g., if eos is '=', "a=" would equal "a". Returns
335 * true for a match, false otherwise.
336 * TODO: This should be placed somewhere else, as it could be useful in
337 * other places too.
338 */
339static bool str_equal(const char* s1, const char* s2, char eos)
340{
341 char c1 = 0;
342 char c2 = 0;
343
344 while (*s1 && *s2 && (*s1 != eos) && (*s2 != eos))
345 {
346 if ((c1 = toupper(*s1)) != (c2 = toupper(*s2)))
347 {
348 return false;
349 }
350
351 s1++;
352 s2++;
353 }
354
355 if (c1 == eos)
356 {
357 c1 = '\0';
358 }
359
360 if (c2 == eos)
361 {
362 c2 = '\0';
363 }
364
365 return c1 == c2;
366}
367
368/* Check for a ReplayGain tag conforming to the "VorbisGain standard". If
369 * found, set the mp3entry accordingly. If value is NULL, key is expected
370 * to be on the "key=value" format, and the comparion/extraction is done
371 * accordingly. buffer is where to store the text contents of the gain tags;
372 * up to length bytes (including end nil) can be written.
373 * Returns number of bytes written to the tag text buffer, or zero if
374 * no ReplayGain tag was found (or nothing was copied to the buffer for
375 * other reasons).
376 */
377long parse_replaygain(const char* key, const char* value,
378 struct mp3entry* entry, char* buffer, int length)
379{
380 const char* val = value;
381 char **p = NULL;
382 char eos = '\0';
383
384 if (!val)
385 {
386 if (!(val = strchr(key, '=')))
387 {
388 return 0;
389 }
390
391 val++;
392 eos = '=';
393 }
394
395 if (str_equal(key, "replaygain_track_gain", eos)
396 || (str_equal(key, "rg_radio", eos) && !entry->track_gain))
397 {
398 entry->track_gain = get_replaygain(val);
399 p = &(entry->track_gain_string);
400 }
401 else if (str_equal(key, "replaygain_album_gain", eos)
402 || (str_equal(key, "rg_audiophile", eos) && !entry->album_gain))
403 {
404 entry->album_gain = get_replaygain(val);
405 p = &(entry->album_gain_string);
406 }
407 else if (str_equal(key, "replaygain_track_peak", eos)
408 || (str_equal(key, "rg_peak", eos) && !entry->track_peak))
409 {
410 entry->track_peak = get_replaypeak(val);
411 }
412 else if (str_equal(key, "replaygain_album_peak", eos))
413 {
414 entry->album_peak = get_replaypeak(val);
415 }
416
417 if (p)
418 {
419 int len = strlen(val);
420
421 len = MIN(len, length - 1);
422
423 /* A few characters just isn't interesting... */
424 if (len > 1)
425 {
426 strncpy(buffer, val, len);
427 buffer[len] = 0;
428 *p = buffer;
429 return len + 1;
430 }
431 }
432
433 return 0;
434}