decoder/gme: simplify ParseContainerPath()

Use simple string and path parsing functions instead of GLib's
g_pattern_match(), which was used in a very clumsy way.
This commit is contained in:
Max Kellermann 2014-12-02 07:11:11 +01:00
parent 27b4c62bc1
commit 5899a272ef
2 changed files with 27 additions and 34 deletions

View File

@ -341,8 +341,6 @@ AC_ARG_ENABLE(gme,
AS_HELP_STRING([--enable-gme], AS_HELP_STRING([--enable-gme],
[enable Blargg's game music emulator plugin]),, [enable Blargg's game music emulator plugin]),,
enable_gme=auto) enable_gme=auto)
MPD_DEPENDS([enable_gme], [enable_glib],
[Cannot use --enable-gme with --disable-glib])
AC_ARG_ENABLE(httpd-output, AC_ARG_ENABLE(httpd-output,
AS_HELP_STRING([--enable-httpd-output], AS_HELP_STRING([--enable-httpd-output],

View File

@ -23,6 +23,7 @@
#include "CheckAudioFormat.hxx" #include "CheckAudioFormat.hxx"
#include "tag/TagHandler.hxx" #include "tag/TagHandler.hxx"
#include "fs/Path.hxx" #include "fs/Path.hxx"
#include "fs/AllocatedPath.hxx"
#include "util/Alloc.hxx" #include "util/Alloc.hxx"
#include "util/FormatString.hxx" #include "util/FormatString.hxx"
#include "util/UriUtil.hxx" #include "util/UriUtil.hxx"
@ -30,7 +31,6 @@
#include "util/Domain.hxx" #include "util/Domain.hxx"
#include "Log.hxx" #include "Log.hxx"
#include <glib.h>
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -48,10 +48,27 @@ static constexpr unsigned GME_BUFFER_SAMPLES =
GME_BUFFER_FRAMES * GME_CHANNELS; GME_BUFFER_FRAMES * GME_CHANNELS;
struct GmeContainerPath { struct GmeContainerPath {
char *path; AllocatedPath path;
unsigned track; unsigned track;
}; };
gcc_pure
static unsigned
ParseSubtuneName(const char *base)
{
if (memcmp(base, SUBTUNE_PREFIX, sizeof(SUBTUNE_PREFIX) - 1) != 0)
return 0;
base += sizeof(SUBTUNE_PREFIX) - 1;
char *endptr;
auto track = strtoul(base, &endptr, 10);
if (endptr == base || *endptr != '.')
return 0;
return track;
}
/** /**
* returns the file path stripped of any /tune_xxx.* subtune suffix * returns the file path stripped of any /tune_xxx.* subtune suffix
* and the track number (or 0 if no "tune_xxx" suffix is present). * and the track number (or 0 if no "tune_xxx" suffix is present).
@ -59,33 +76,13 @@ struct GmeContainerPath {
static GmeContainerPath static GmeContainerPath
ParseContainerPath(Path path_fs) ParseContainerPath(Path path_fs)
{ {
const char *subtune_suffix = uri_get_suffix(path_fs.c_str()); const Path base = path_fs.GetBase();
char *path_container = xstrdup(path_fs.c_str()); unsigned track;
if (base.IsNull() ||
(track = ParseSubtuneName(base.c_str())) < 1)
return { AllocatedPath(path_fs), 0 };
char pat[64]; return { path_fs.GetDirectoryName(), track - 1 };
snprintf(pat, sizeof(pat), "%s%s",
"*/" SUBTUNE_PREFIX "???.",
subtune_suffix);
GPatternSpec *path_with_subtune = g_pattern_spec_new(pat);
if (!g_pattern_match(path_with_subtune,
strlen(path_container), path_container, nullptr)) {
g_pattern_spec_free(path_with_subtune);
return { path_container, 0 };
}
unsigned track = 0;
char *sub = g_strrstr(path_container, "/" SUBTUNE_PREFIX);
if (sub != nullptr) {
*sub = '\0';
sub += strlen("/" SUBTUNE_PREFIX);
int song_num = strtol(sub, nullptr, 10);
if (song_num >= 1)
track = song_num - 1;
}
g_pattern_spec_free(path_with_subtune);
return { path_container, track };
} }
static char * static char *
@ -120,8 +117,7 @@ gme_file_decode(Decoder &decoder, Path path_fs)
Music_Emu *emu; Music_Emu *emu;
const char *gme_err = const char *gme_err =
gme_open_file(container.path, &emu, GME_SAMPLE_RATE); gme_open_file(container.path.c_str(), &emu, GME_SAMPLE_RATE);
free(container.path);
if (gme_err != nullptr) { if (gme_err != nullptr) {
LogWarning(gme_domain, gme_err); LogWarning(gme_domain, gme_err);
return; return;
@ -256,8 +252,7 @@ gme_scan_file(Path path_fs,
Music_Emu *emu; Music_Emu *emu;
const char *gme_err = const char *gme_err =
gme_open_file(container.path, &emu, GME_SAMPLE_RATE); gme_open_file(container.path.c_str(), &emu, GME_SAMPLE_RATE);
free(container.path);
if (gme_err != nullptr) { if (gme_err != nullptr) {
LogWarning(gme_domain, gme_err); LogWarning(gme_domain, gme_err);
return false; return false;