summaryrefslogtreecommitdiffstats
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/lib/SOURCES6
-rw-r--r--apps/plugins/lib/id3.c46
-rw-r--r--apps/plugins/lib/id3.h26
-rw-r--r--apps/plugins/lib/mul_id3.c182
-rw-r--r--apps/plugins/lib/mul_id3.h28
-rw-r--r--apps/plugins/pictureflow/pictureflow.c223
6 files changed, 308 insertions, 203 deletions
diff --git a/apps/plugins/lib/SOURCES b/apps/plugins/lib/SOURCES
index bff9017404..09a8b1c5ed 100644
--- a/apps/plugins/lib/SOURCES
+++ b/apps/plugins/lib/SOURCES
@@ -69,3 +69,9 @@ kbd_helper.c
#ifdef HAVE_TOUCHSCREEN
pluginlib_touchscreen.c
#endif
+
+id3.c
+
+#ifdef HAVE_TAGCACHE
+mul_id3.c
+#endif
diff --git a/apps/plugins/lib/id3.c b/apps/plugins/lib/id3.c
new file mode 100644
index 0000000000..0ce1736ffe
--- /dev/null
+++ b/apps/plugins/lib/id3.c
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2023 Christian Soffke
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+
+bool retrieve_id3(struct mp3entry *id3, const char* file, bool try_tagcache)
+{
+ bool ret = false;
+ int fd;
+
+#if defined (HAVE_TAGCACHE) && defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
+ if (try_tagcache && rb->tagcache_fill_tags(id3, file))
+ {
+ rb->strlcpy(id3->path, file, sizeof(id3->path));
+ return true;
+ }
+#else
+ (void) try_tagcache;
+#endif
+
+ fd = rb->open(file, O_RDONLY);
+ if (fd >= 0)
+ {
+ if (rb->get_metadata(id3, fd, file))
+ ret = true;
+ rb->close(fd);
+ }
+ return ret;
+}
diff --git a/apps/plugins/lib/id3.h b/apps/plugins/lib/id3.h
new file mode 100644
index 0000000000..292556d0c4
--- /dev/null
+++ b/apps/plugins/lib/id3.h
@@ -0,0 +1,26 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2023 Christian Soffke
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef ID3_H
+#define ID3_H
+
+bool retrieve_id3(struct mp3entry *id3, const char* file, bool try_tagcache);
+
+#endif /* ID3_H */ \ No newline at end of file
diff --git a/apps/plugins/lib/mul_id3.c b/apps/plugins/lib/mul_id3.c
new file mode 100644
index 0000000000..5c8f4d9d9c
--- /dev/null
+++ b/apps/plugins/lib/mul_id3.c
@@ -0,0 +1,182 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2023 Christian Soffke
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "plugin.h"
+#include "mul_id3.h"
+
+struct multiple_tracks_id3 {
+ unsigned long length;
+ unsigned long filesize;
+ unsigned long frequency;
+ unsigned int artist_hash;
+ unsigned int composer_hash;
+ unsigned int albumartist_hash;
+ unsigned int grouping_hash;
+ unsigned int comment_hash;
+ unsigned int album_hash;
+ unsigned int genre_hash;
+ unsigned int codectype;
+ unsigned int bitrate;
+ int year;
+ bool filesize_ovf;
+ bool length_ovf;
+ bool vbr;
+};
+
+static struct multiple_tracks_id3 mul_id3;
+
+
+/* Calculate modified FNV hash of string
+ * has good avalanche behaviour and uniform distribution
+ * see http://home.comcast.net/~bretm/hash/ */
+static unsigned int mfnv(char *str)
+{
+ const unsigned int p = 16777619;
+ unsigned int hash = 0x811C9DC5; // 2166136261;
+
+ if (!str)
+ return 0;
+
+ while(*str)
+ hash = (hash ^ *str++) * p;
+ hash += hash << 13;
+ hash ^= hash >> 7;
+ hash += hash << 3;
+ hash ^= hash >> 17;
+ hash += hash << 5;
+ return hash;
+}
+
+void init_mul_id3(void)
+{
+ mul_id3.artist_hash = 0;
+ mul_id3.album_hash = 0;
+ mul_id3.genre_hash = 0;
+ mul_id3.composer_hash = 0;
+ mul_id3.albumartist_hash = 0;
+ mul_id3.grouping_hash = 0;
+ mul_id3.comment_hash = 0;
+ mul_id3.codectype = 0;
+ mul_id3.vbr = false;
+ mul_id3.bitrate = 0;
+ mul_id3.frequency = 0;
+ mul_id3.length = 0;
+ mul_id3.filesize = 0;
+ mul_id3.year = 0;
+ mul_id3.length_ovf = false;
+ mul_id3.filesize_ovf = false;
+}
+
+void collect_id3(struct mp3entry *id3, bool is_first_track)
+{
+ if (is_first_track)
+ {
+ mul_id3.artist_hash = mfnv(id3->artist);
+ mul_id3.album_hash = mfnv(id3->album);
+ mul_id3.genre_hash = mfnv(id3->genre_string);
+ mul_id3.composer_hash = mfnv(id3->composer);
+ mul_id3.albumartist_hash = mfnv(id3->albumartist);
+ mul_id3.grouping_hash = mfnv(id3->grouping);
+ mul_id3.comment_hash = mfnv(id3->comment);
+ mul_id3.codectype = id3->codectype;
+ mul_id3.vbr = id3->vbr;
+ mul_id3.bitrate = id3->bitrate;
+ mul_id3.frequency = id3->frequency;
+ mul_id3.year = id3->year;
+ }
+ else
+ {
+ if (mul_id3.artist_hash && (mfnv(id3->artist) != mul_id3.artist_hash))
+ mul_id3.artist_hash = 0;
+ if (mul_id3.album_hash && (mfnv(id3->album) != mul_id3.album_hash))
+ mul_id3.album_hash = 0;
+ if (mul_id3.genre_hash && (mfnv(id3->genre_string) != mul_id3.genre_hash))
+ mul_id3.genre_hash = 0;
+ if (mul_id3.composer_hash && (mfnv(id3->composer) != mul_id3.composer_hash))
+ mul_id3.composer_hash = 0;
+ if (mul_id3.albumartist_hash && (mfnv(id3->albumartist) !=
+ mul_id3.albumartist_hash))
+ mul_id3.albumartist_hash = 0;
+ if (mul_id3.grouping_hash && (mfnv(id3->grouping) != mul_id3.grouping_hash))
+ mul_id3.grouping_hash = 0;
+ if (mul_id3.comment_hash && (mfnv(id3->comment) != mul_id3.comment_hash))
+ mul_id3.comment_hash = 0;
+
+ if (mul_id3.codectype && (id3->codectype != mul_id3.codectype))
+ mul_id3.codectype = AFMT_UNKNOWN;
+ if (mul_id3.bitrate && (id3->bitrate != mul_id3.bitrate ||
+ id3->vbr != mul_id3.vbr))
+ mul_id3.bitrate = 0;
+ if (mul_id3.frequency && (id3->frequency != mul_id3.frequency))
+ mul_id3.frequency = 0;
+ if (mul_id3.year && (id3->year != mul_id3.year))
+ mul_id3.year = 0;
+ }
+
+ if (ULONG_MAX - mul_id3.length < id3->length)
+ {
+ mul_id3.length_ovf = true;
+ mul_id3.length = 0;
+ }
+ else if (!mul_id3.length_ovf)
+ mul_id3.length += id3->length;
+
+ if (INT_MAX - mul_id3.filesize < id3->filesize) /* output_dyn_value expects int */
+ {
+ mul_id3.filesize_ovf = true;
+ mul_id3.filesize = 0;
+ }
+ else if (!mul_id3.filesize_ovf)
+ mul_id3.filesize += id3->filesize;
+}
+
+void write_id3_mul_tracks(struct mp3entry *id3)
+{
+ id3->path[0] = '\0';
+ id3->title = NULL;
+ if (!mul_id3.artist_hash)
+ id3->artist = NULL;
+ if (!mul_id3.album_hash)
+ id3->album = NULL;
+ if (!mul_id3.genre_hash)
+ id3->genre_string = NULL;
+ if (!mul_id3.composer_hash)
+ id3->composer = NULL;
+ if (!mul_id3.albumartist_hash)
+ id3->albumartist = NULL;
+ if (!mul_id3.grouping_hash)
+ id3->grouping = NULL;
+ if (!mul_id3.comment_hash)
+ id3->comment = NULL;
+ id3->disc_string = NULL;
+ id3->track_string = NULL;
+ id3->year_string = NULL;
+ id3->year = mul_id3.year;
+ id3->length = mul_id3.length;
+ id3->filesize = mul_id3.filesize;
+ id3->frequency = mul_id3.frequency;
+ id3->bitrate = mul_id3.bitrate;
+ id3->codectype = mul_id3.codectype;
+ id3->vbr = mul_id3.vbr;
+ id3->discnum = 0;
+ id3->tracknum = 0;
+ id3->track_level = 0;
+ id3->album_level = 0;
+}
diff --git a/apps/plugins/lib/mul_id3.h b/apps/plugins/lib/mul_id3.h
new file mode 100644
index 0000000000..71da10e87e
--- /dev/null
+++ b/apps/plugins/lib/mul_id3.h
@@ -0,0 +1,28 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2023 Christian Soffke
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef MUL_ID3_H
+#define MUL_ID3_H
+
+void init_mul_id3(void);
+void collect_id3(struct mp3entry *id3, bool is_first_track);
+void write_id3_mul_tracks(struct mp3entry *id3);
+
+#endif /* MUL_ID3_H */ \ No newline at end of file
diff --git a/apps/plugins/pictureflow/pictureflow.c b/apps/plugins/pictureflow/pictureflow.c
index b231390420..999ed2563f 100644
--- a/apps/plugins/pictureflow/pictureflow.c
+++ b/apps/plugins/pictureflow/pictureflow.c
@@ -33,6 +33,7 @@
#include "lib/grey.h"
#include "lib/mylcd.h"
#include "lib/feature_wrappers.h"
+#include "lib/id3.h"
/******************************* Globals ***********************************/
static fb_data *lcd_fb;
@@ -44,6 +45,7 @@ static fb_data *lcd_fb;
#if PF_PLAYBACK_CAPABLE
#include "lib/playback_control.h"
+#include "lib/mul_id3.h"
#endif
#define PF_PREV ACTION_STD_PREV
@@ -397,26 +399,6 @@ struct track_data {
#endif
};
-#if PF_PLAYBACK_CAPABLE
-struct multiple_tracks_id3 {
- unsigned long length;
- unsigned long filesize;
- unsigned long frequency;
- unsigned int artist_hash;
- unsigned int composer_hash;
- unsigned int albumartist_hash;
- unsigned int grouping_hash;
- unsigned int comment_hash;
- unsigned int album_hash;
- unsigned int genre_hash;
- unsigned int codectype;
- unsigned int bitrate;
- bool filesize_ovf;
- bool length_ovf;
- bool vbr;
-};
-#endif
-
struct rect {
int left;
int right;
@@ -2096,15 +2078,13 @@ static inline void free_borrowed_tracks(void)
static bool get_albumart_for_index_from_db(const int slide_index, char *buf,
int buflen)
{
- if ( slide_index == -1 )
- {
- rb->strlcpy( buf, EMPTY_SLIDE, buflen );
- }
+ bool ret;
+ if (slide_index == -1)
+ rb->strlcpy(buf, EMPTY_SLIDE, buflen);
if (tcs.valid || !rb->tagcache_search(&tcs, tag_filename))
return false;
- bool result;
/* find the first track of the album */
rb->tagcache_search_add_filter(&tcs, tag_album,
pf_idx.album_index[slide_index].seek);
@@ -2112,35 +2092,12 @@ static bool get_albumart_for_index_from_db(const int slide_index, char *buf,
rb->tagcache_search_add_filter(&tcs, tag_albumartist,
pf_idx.album_index[slide_index].artist_seek);
- if ( rb->tagcache_get_next(&tcs) ) {
- int fd;
-
-#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
- if (rb->tagcache_fill_tags(&id3, tcs.result))
- {
- rb->strlcpy(id3.path, tcs.result, sizeof(id3.path));
- }
- else
-#endif
- {
- fd = rb->open(tcs.result, O_RDONLY);
- if (fd) {
- rb->get_metadata(&id3, fd, tcs.result);
- rb->close(fd);
- }
- }
+ ret = rb->tagcache_get_next(&tcs) &&
+ retrieve_id3(&id3, tcs.result, true) &&
+ search_albumart_files(&id3, ":", buf, buflen);
- if ( search_albumart_files(&id3, ":", buf, buflen) )
- result = true;
- else
- result = false;
- }
- else {
- /* did not find a matching track */
- result = false;
- }
rb->tagcache_search_finish(&tcs);
- return result;
+ return ret;
}
/**
@@ -4032,145 +3989,21 @@ static void select_prev_album(void)
}
#if PF_PLAYBACK_CAPABLE
-static void collect_id3(struct multiple_tracks_id3 *mul_id3, bool is_first_track)
-{
- if (is_first_track)
- {
- mul_id3->artist_hash = mfnv(id3.artist);
- mul_id3->album_hash = mfnv(id3.album);
- mul_id3->genre_hash = mfnv(id3.genre_string);
- mul_id3->composer_hash = mfnv(id3.composer);
- mul_id3->albumartist_hash = mfnv(id3.albumartist);
- mul_id3->grouping_hash = mfnv(id3.grouping);
- mul_id3->comment_hash = mfnv(id3.comment);
- mul_id3->codectype = id3.codectype;
- mul_id3->vbr = id3.vbr;
- mul_id3->bitrate = id3.bitrate;
- mul_id3->frequency = id3.frequency;
- }
- else
- {
- if (mul_id3->artist_hash && (mfnv(id3.artist) != mul_id3->artist_hash))
- mul_id3->artist_hash = 0;
- if (mul_id3->album_hash && (mfnv(id3.album) != mul_id3->album_hash))
- mul_id3->album_hash = 0;
- if (mul_id3->genre_hash && (mfnv(id3.genre_string) != mul_id3->genre_hash))
- mul_id3->genre_hash = 0;
- if (mul_id3->composer_hash && (mfnv(id3.composer) != mul_id3->composer_hash))
- mul_id3->composer_hash = 0;
- if (mul_id3->albumartist_hash && (mfnv(id3.albumartist) !=
- mul_id3->albumartist_hash))
- mul_id3->albumartist_hash = 0;
- if (mul_id3->grouping_hash && (mfnv(id3.grouping) != mul_id3->grouping_hash))
- mul_id3->grouping_hash = 0;
- if (mul_id3->comment_hash && (mfnv(id3.comment) != mul_id3->comment_hash))
- mul_id3->comment_hash = 0;
-
- if (mul_id3->codectype && (id3.codectype != mul_id3->codectype))
- mul_id3->codectype = AFMT_UNKNOWN;
- if (mul_id3->bitrate && (id3.bitrate != mul_id3->bitrate ||
- id3.vbr != mul_id3->vbr))
- mul_id3->bitrate = 0;
- if (mul_id3->frequency && (id3.frequency != mul_id3->frequency))
- mul_id3->frequency = 0;
- }
-
- if (ULONG_MAX - mul_id3->length < id3.length)
- {
- mul_id3->length_ovf = true;
- mul_id3->length = 0;
- }
- else if (!mul_id3->length_ovf)
- mul_id3->length += id3.length;
-
- if (INT_MAX - mul_id3->filesize < id3.filesize) /* output_dyn_value expects int */
- {
- mul_id3->filesize_ovf = true;
- mul_id3->filesize = 0;
- }
- else if (!mul_id3->filesize_ovf)
- mul_id3->filesize += id3.filesize;
-}
-
-
-static void write_id3_mul_tracks(struct multiple_tracks_id3 *mul_id3)
-{
- id3.path[0] = '\0';
- id3.title = NULL;
- if (!mul_id3->artist_hash)
- id3.artist = NULL;
- if (!mul_id3->album_hash)
- id3.album = NULL;
- if (!mul_id3->genre_hash)
- id3.genre_string = NULL;
- if (!mul_id3->composer_hash)
- id3.composer = NULL;
- if (!mul_id3->albumartist_hash)
- id3.albumartist = NULL;
- if (!mul_id3->grouping_hash)
- id3.grouping = NULL;
- if (!mul_id3->comment_hash)
- id3.comment = NULL;
- id3.disc_string = NULL;
- id3.track_string = NULL;
- id3.year_string = NULL;
- id3.year = pf_idx.album_index[center_index].year;
- id3.length = mul_id3->length;
- id3.filesize = mul_id3->filesize;
- id3.frequency = mul_id3->frequency;
- id3.bitrate = mul_id3->bitrate;
- id3.codectype = mul_id3->codectype;
- id3.vbr = mul_id3->vbr;
- id3.discnum = 0;
- id3.tracknum = 0;
- id3.track_level = 0;
- id3.album_level = 0;
-}
-
-static void init_mul_id3(struct multiple_tracks_id3 *mul_id3)
-{
- mul_id3->artist_hash = 0;
- mul_id3->album_hash = 0;
- mul_id3->genre_hash = 0;
- mul_id3->composer_hash = 0;
- mul_id3->albumartist_hash = 0;
- mul_id3->grouping_hash = 0;
- mul_id3->comment_hash = 0;
- mul_id3->codectype = 0;
- mul_id3->vbr = false;
- mul_id3->bitrate = 0;
- mul_id3->frequency = 0;
- mul_id3->length = 0;
- mul_id3->filesize = 0;
- mul_id3->length_ovf = false;
- mul_id3->filesize_ovf = false;
-}
-
static int show_id3_info(const char *selected_file)
{
- int fd, i;
+ int i;
unsigned long last_tick;
const char *file_name;
- bool id3_retrieval_successful;
bool is_multiple_tracks = insert_whole_album && pf_tracks.count > 1;
- struct multiple_tracks_id3 mul_id3;
- init_mul_id3(&mul_id3);
+ init_mul_id3();
last_tick = *(rb->current_tick) + HZ/2;
rb->splash_progress_set_delay(HZ / 2); /* wait 1/2 sec before progress */
i = 0;
do {
- id3_retrieval_successful = false;
file_name = i == 0 ? selected_file : get_track_filename(i);
- fd = rb->open(file_name, O_RDONLY);
- if (fd >= 0)
- {
- if (rb->get_metadata(&id3, fd, file_name))
- id3_retrieval_successful = true;
- rb->close(fd);
- }
- if (!id3_retrieval_successful)
+ if (!retrieve_id3(&id3, file_name, false))
return 0;
if (is_multiple_tracks)
@@ -4184,13 +4017,13 @@ static int show_id3_info(const char *selected_file)
last_tick = *(rb->current_tick);
}
- collect_id3(&mul_id3, i == 0);
+ collect_id3(&id3, i == 0);
rb->yield();
}
} while (++i < pf_tracks.count && is_multiple_tracks);
if (is_multiple_tracks)
- write_id3_mul_tracks(&mul_id3);
+ write_id3_mul_tracks(&id3);
return rb->browse_id3(&id3, 0, 0, NULL) ? PLUGIN_USB_CONNECTED : 0;
}
@@ -4520,31 +4353,15 @@ static void draw_album_text(void)
static void set_initial_slide(const char* selected_file)
{
- if (selected_file == NULL)
+ if (selected_file)
+ set_current_slide(retrieve_id3(&id3, selected_file, true) ?
+ id3_get_index(&id3) :
+ pf_cfg.last_album);
+ else
set_current_slide(rb->audio_status() ?
id3_get_index(rb->audio_current_track()) :
pf_cfg.last_album);
- else
- {
-#if defined(HAVE_TC_RAMCACHE) && defined(HAVE_DIRCACHE)
- if (rb->tagcache_fill_tags(&id3, selected_file))
- set_current_slide(id3_get_index(&id3));
- else
-#endif
- {
- int fd = rb->open(selected_file, O_RDONLY);
- if (fd >= 0)
- {
- if (rb->get_metadata(&id3, fd, selected_file))
- set_current_slide(id3_get_index(&id3));
- else
- set_current_slide(pf_cfg.last_album);
- rb->close(fd);
- }
- else
- set_current_slide(pf_cfg.last_album);
- }
- }
+
}
/**