decoder/sidplay: implemented songlength database
[mk: added autoconf test; fixed songlen_data_size type]
This commit is contained in:
parent
85ce9aa7de
commit
cde9408bd8
1
NEWS
1
NEWS
|
@ -16,6 +16,7 @@ ver 0.16 (20??/??/??)
|
||||||
- flac: load external cue sheet when no internal one
|
- flac: load external cue sheet when no internal one
|
||||||
- mpg123: new decoder plugin based on libmpg123
|
- mpg123: new decoder plugin based on libmpg123
|
||||||
- sidplay: support sub-tunes
|
- sidplay: support sub-tunes
|
||||||
|
- sidplay: implemented songlength database
|
||||||
* encoders:
|
* encoders:
|
||||||
- twolame: new encoder plugin based on libtwolame
|
- twolame: new encoder plugin based on libtwolame
|
||||||
* output:
|
* output:
|
||||||
|
|
|
@ -554,12 +554,17 @@ if test x$enable_sidplay != xno; then
|
||||||
# library name triggers an autoconf bug
|
# library name triggers an autoconf bug
|
||||||
AC_CHECK_LIB(resid-builder, main,
|
AC_CHECK_LIB(resid-builder, main,
|
||||||
[found_sidplay=yes], [found_sidplay=no])
|
[found_sidplay=yes], [found_sidplay=no])
|
||||||
|
|
||||||
|
if test x$found_sidplay = xyes; then
|
||||||
|
AC_HAVE_LIBRARY(sidutils,, [found_sidplay=no])
|
||||||
|
fi
|
||||||
|
|
||||||
MPD_AUTO_RESULT(sidplay, [sidplay decoder plugin],
|
MPD_AUTO_RESULT(sidplay, [sidplay decoder plugin],
|
||||||
[libresid-builder not found])
|
[libresid-builder or libsidutils not found])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test x$enable_sidplay = xyes; then
|
if test x$enable_sidplay = xyes; then
|
||||||
AC_SUBST(SIDPLAY_LIBS,"-lsidplay2 -lresid-builder")
|
AC_SUBST(SIDPLAY_LIBS,"-lsidplay2 -lresid-builder -lsidutils")
|
||||||
AC_SUBST(SIDPLAY_CFLAGS,)
|
AC_SUBST(SIDPLAY_CFLAGS,)
|
||||||
|
|
||||||
AC_DEFINE(ENABLE_SIDPLAY, 1, [Define for libsidplay2 support])
|
AC_DEFINE(ENABLE_SIDPLAY, 1, [Define for libsidplay2 support])
|
||||||
|
|
|
@ -363,3 +363,25 @@ input {
|
||||||
#id3v1_encoding "ISO-8859-1"
|
#id3v1_encoding "ISO-8859-1"
|
||||||
#
|
#
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
|
# SIDPlay decoder #############################################################
|
||||||
|
#
|
||||||
|
# songlength_database:
|
||||||
|
# Location of your songlengths file, as distributed with the HVSC.
|
||||||
|
# The sidplay plugin checks this for matching MD5 fingerprints.
|
||||||
|
# See http://www.c64.org/HVSC/DOCUMENTS/Songlengths.faq
|
||||||
|
#
|
||||||
|
# default_songlength:
|
||||||
|
# This is the default playing time in seconds for songs not in the
|
||||||
|
# songlength database, or in case you're not using a database.
|
||||||
|
# A value of 0 means play indefinitely.
|
||||||
|
#
|
||||||
|
#decoder {
|
||||||
|
# plugin "sidplay"
|
||||||
|
# songlength_database "/media/C64Music/DOCUMENTS/Songlengths.txt"
|
||||||
|
# default_songlength "120"
|
||||||
|
#}
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ extern "C" {
|
||||||
|
|
||||||
#include <sidplay/sidplay2.h>
|
#include <sidplay/sidplay2.h>
|
||||||
#include <sidplay/builders/resid.h>
|
#include <sidplay/builders/resid.h>
|
||||||
|
#include <sidplay/utils/SidTuneMod.h>
|
||||||
|
|
||||||
#undef G_LOG_DOMAIN
|
#undef G_LOG_DOMAIN
|
||||||
#define G_LOG_DOMAIN "sidplay"
|
#define G_LOG_DOMAIN "sidplay"
|
||||||
|
@ -34,12 +35,48 @@ extern "C" {
|
||||||
#define SUBTUNE_PREFIX "tune_"
|
#define SUBTUNE_PREFIX "tune_"
|
||||||
|
|
||||||
static GPatternSpec *path_with_subtune;
|
static GPatternSpec *path_with_subtune;
|
||||||
|
static const char *songlength_file;
|
||||||
|
static GKeyFile *songlength_database;
|
||||||
|
|
||||||
static bool all_files_are_containers;
|
static bool all_files_are_containers;
|
||||||
|
static unsigned default_songlength;
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
sidplay_init(const struct config_param *param)
|
sidplay_init(const struct config_param *param)
|
||||||
{
|
{
|
||||||
|
GError *err=NULL;
|
||||||
|
gchar *songlen_data;
|
||||||
|
gsize songlen_data_size;
|
||||||
|
|
||||||
|
/* read the songlengths database file */
|
||||||
|
songlength_file=config_get_block_string(param,
|
||||||
|
"songlength_database", NULL);
|
||||||
|
if(songlength_file) {
|
||||||
|
if(g_file_get_contents(songlength_file, &songlen_data, &songlen_data_size, NULL)) {
|
||||||
|
/* replace any ; comment characters with # */
|
||||||
|
for(int i=0; i<songlen_data_size; i++)
|
||||||
|
if(songlen_data[i]==';') songlen_data[i]='#';
|
||||||
|
|
||||||
|
songlength_database=g_key_file_new();
|
||||||
|
if(!g_key_file_load_from_data(songlength_database,
|
||||||
|
songlen_data, songlen_data_size,
|
||||||
|
G_KEY_FILE_NONE, &err)) {
|
||||||
|
g_warning("unable to parse songlengths file %s: %s",
|
||||||
|
songlength_file, err->message);
|
||||||
|
g_key_file_free(songlength_database);
|
||||||
|
songlength_database=NULL;
|
||||||
|
}
|
||||||
|
g_key_file_set_list_separator(songlength_database, ' ');
|
||||||
|
g_free(songlen_data);
|
||||||
|
} else {
|
||||||
|
g_warning("unable to read songlengths file %s: %s",
|
||||||
|
songlength_file, err->message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
default_songlength=config_get_block_unsigned(param,
|
||||||
|
"default_songlength", 0);
|
||||||
|
|
||||||
all_files_are_containers=config_get_block_bool(param,
|
all_files_are_containers=config_get_block_bool(param,
|
||||||
"all_files_are_containers", true);
|
"all_files_are_containers", true);
|
||||||
|
|
||||||
|
@ -53,6 +90,9 @@ void
|
||||||
sidplay_finish()
|
sidplay_finish()
|
||||||
{
|
{
|
||||||
g_pattern_spec_free(path_with_subtune);
|
g_pattern_spec_free(path_with_subtune);
|
||||||
|
|
||||||
|
if(songlength_database)
|
||||||
|
g_key_file_free(songlength_database);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -97,6 +137,49 @@ get_song_num(const char *path_fs)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get the song length in seconds */
|
||||||
|
static int
|
||||||
|
get_song_length(const char *path_fs)
|
||||||
|
{
|
||||||
|
if (songlength_database == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
gchar *sid_file=get_container_name(path_fs);
|
||||||
|
SidTuneMod tune(sid_file);
|
||||||
|
g_free(sid_file);
|
||||||
|
if(!tune) {
|
||||||
|
g_warning("failed to load file for calculating md5 sum");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
char md5sum[SIDTUNE_MD5_LENGTH+1];
|
||||||
|
tune.createMD5(md5sum);
|
||||||
|
|
||||||
|
int song_num=get_song_num(path_fs);
|
||||||
|
|
||||||
|
gsize num_items;
|
||||||
|
gchar **values=g_key_file_get_string_list(songlength_database,
|
||||||
|
"Database", md5sum, &num_items, NULL);
|
||||||
|
if(!values || song_num>num_items) {
|
||||||
|
g_strfreev(values);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int minutes=strtol(values[song_num-1], NULL, 10);
|
||||||
|
if(errno==EINVAL) minutes=0;
|
||||||
|
|
||||||
|
int seconds;
|
||||||
|
char *ptr=strchr(values[song_num-1], ':');
|
||||||
|
if(ptr) {
|
||||||
|
seconds=strtol(ptr+1, NULL, 10);
|
||||||
|
if(errno==EINVAL) seconds=0;
|
||||||
|
} else
|
||||||
|
seconds=0;
|
||||||
|
|
||||||
|
g_strfreev(values);
|
||||||
|
|
||||||
|
return (minutes*60)+seconds;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sidplay_file_decode(struct decoder *decoder, const char *path_fs)
|
sidplay_file_decode(struct decoder *decoder, const char *path_fs)
|
||||||
{
|
{
|
||||||
|
@ -232,6 +315,10 @@ sidplay_tag_dup(const char *path_fs)
|
||||||
tag_add_item(tag, TAG_ITEM_TRACK, track);
|
tag_add_item(tag, TAG_ITEM_TRACK, track);
|
||||||
g_free(track);
|
g_free(track);
|
||||||
|
|
||||||
|
/* time */
|
||||||
|
int song_len=get_song_length(path_fs);
|
||||||
|
if(song_len!=-1) tag->time=song_len;
|
||||||
|
|
||||||
return tag;
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue