summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBenjamin Drung <bdrung@ubuntu.com>2010-06-14 00:14:42 +0200
committerBenjamin Drung <bdrung@ubuntu.com>2010-06-14 00:14:42 +0200
commit42318926e1c1585ccc266c4607cb1d6e855bd0b9 (patch)
tree40144e79fc7ef2b106e7c23d77fb8a9ba0af5216 /src
parent56ad9eb46da6e9b941795b17fb4fa18b6f75c4ae (diff)
Imported Upstream version 2.4~alpha1
Diffstat (limited to 'src')
-rw-r--r--src/Makefile2
-rw-r--r--src/audacious/Makefile25
-rw-r--r--src/audacious/af_compat.h104
-rw-r--r--src/audacious/af_equalizer.c196
-rw-r--r--src/audacious/audconfig.c178
-rw-r--r--src/audacious/audconfig.h10
-rw-r--r--src/audacious/build_stamp.h6
-rw-r--r--src/audacious/credits.c2
-rw-r--r--src/audacious/dbus.c34
-rw-r--r--src/audacious/effect.c20
-rw-r--r--src/audacious/effect.h3
-rw-r--r--src/audacious/equalizer.c174
-rw-r--r--src/audacious/equalizer.h42
-rw-r--r--src/audacious/equalizer_flow.c113
-rw-r--r--src/audacious/equalizer_flow.h12
-rw-r--r--src/audacious/equalizer_preset.c2
-rw-r--r--src/audacious/flow.h8
-rw-r--r--src/audacious/folder-add.c13
-rw-r--r--src/audacious/images/audacious_player.xpm378
-rw-r--r--src/audacious/input.c129
-rw-r--r--src/audacious/input.h3
-rw-r--r--src/audacious/interface.c9
-rw-r--r--src/audacious/interface.h21
-rw-r--r--src/audacious/main.c64
-rw-r--r--src/audacious/output.c90
-rw-r--r--src/audacious/playback.c152
-rw-r--r--src/audacious/playlist-new.c209
-rw-r--r--src/audacious/playlist-new.h6
-rw-r--r--src/audacious/playlist-utils.c68
-rw-r--r--src/audacious/playlist-utils.h3
-rw-r--r--src/audacious/plugin.h302
-rw-r--r--src/audacious/pluginenum.c120
-rw-r--r--src/audacious/preferences.h8
-rw-r--r--src/audacious/probe.c85
-rw-r--r--src/audacious/probe.h12
-rw-r--r--src/audacious/sync-menu.c715
-rw-r--r--src/audacious/sync-menu.h27
-rw-r--r--src/audacious/ui_albumart.c20
-rw-r--r--src/audacious/ui_albumart.h8
-rw-r--r--src/audacious/ui_fileinfo.c993
-rw-r--r--src/audacious/ui_fileinfo.h32
-rw-r--r--src/audacious/ui_fileinfopopup.c489
-rw-r--r--src/audacious/ui_fileinfopopup.h36
-rw-r--r--src/audacious/ui_misc.h1
-rw-r--r--src/audacious/ui_plugin_menu.c9
-rw-r--r--src/audacious/ui_plugin_menu.h16
-rw-r--r--src/audacious/ui_preferences.c34
-rw-r--r--src/audacious/ui_preferences.h8
-rw-r--r--src/audacious/util.c90
-rw-r--r--src/audacious/util.h8
-rw-r--r--src/audacious/visualization.c1
-rw-r--r--src/audtool/Makefile2
-rw-r--r--src/libaudacious++/Makefile6
-rw-r--r--src/libaudacious++/README1
-rw-r--r--src/libaudacious++/plugin.h36
-rw-r--r--src/libaudcore/audio.c4
-rw-r--r--src/libaudcore/audstrings.c100
-rw-r--r--src/libaudcore/audstrings.h7
-rw-r--r--src/libaudcore/index.c103
-rw-r--r--src/libaudcore/index.h19
-rw-r--r--src/libaudcore/tuple.c15
-rw-r--r--src/libaudcore/tuple.h15
-rw-r--r--src/libaudcore/vfs.c35
-rw-r--r--src/libaudcore/vfs.h184
-rw-r--r--src/libaudcore/vfs_buffer.c18
-rw-r--r--src/libaudcore/vfs_buffered_file.c24
-rw-r--r--src/libaudcore/vfs_common.c22
-rw-r--r--src/libaudgui/Makefile11
-rw-r--r--src/libaudgui/confirm.c98
-rw-r--r--src/libaudgui/infopopup.c428
-rw-r--r--src/libaudgui/infowin.c912
-rw-r--r--src/libaudgui/init.c29
-rw-r--r--src/libaudgui/init.h24
-rw-r--r--src/libaudgui/libaudgui-gtk.h28
-rw-r--r--src/libaudgui/libaudgui.h14
-rw-r--r--src/libaudgui/library-store.c366
-rw-r--r--src/libaudgui/ui_jumptotrack.c6
-rw-r--r--src/libaudgui/ui_playlist_manager.c263
-rw-r--r--src/libaudgui/util.c127
-rw-r--r--src/libaudtag/Makefile12
-rw-r--r--src/libaudtag/aac/aac.c485
-rw-r--r--src/libaudtag/aac/aac.h42
-rwxr-xr-xsrc/libaudtag/ape/ape.c675
-rw-r--r--src/libaudtag/ape/ape.h72
-rw-r--r--src/libaudtag/audtag.c64
-rw-r--r--src/libaudtag/audtag.h41
-rw-r--r--src/libaudtag/id3/frame.h24
-rw-r--r--src/libaudtag/id3/id3.c541
-rw-r--r--src/libaudtag/id3/id3.h118
-rw-r--r--src/libaudtag/id3/id3v1.c145
-rw-r--r--src/libaudtag/id3/id3v1.h36
-rw-r--r--src/libaudtag/id3/id3v22.c890
-rw-r--r--src/libaudtag/id3/id3v22.h30
-rw-r--r--src/libaudtag/id3/id3v24.c1106
-rw-r--r--src/libaudtag/id3/id3v24.h30
-rw-r--r--src/libaudtag/tag_module.c64
-rw-r--r--src/libaudtag/tag_module.h33
-rw-r--r--src/libaudtag/util.c329
-rw-r--r--src/libaudtag/util.h158
-rw-r--r--src/libaudtag/wma/guid.c99
-rw-r--r--src/libaudtag/wma/guid.h20
-rw-r--r--src/libaudtag/wma/module.h23
-rw-r--r--src/libaudtag/wma/wma.c199
-rw-r--r--src/libaudtag/wma/wma.h31
-rw-r--r--src/libaudtag/wma/wma_fmt.h22
-rw-r--r--src/libeggsmclient/Makefile2
-rw-r--r--src/libguess/Makefile3
-rw-r--r--src/libguess/guess.c1
-rw-r--r--src/libguess/libguess.h2
-rw-r--r--src/libguess/polish_impl.c53
-rw-r--r--src/libid3tag/Makefile34
-rw-r--r--src/libid3tag/README.audacious9
-rw-r--r--src/libid3tag/compat.c412
-rw-r--r--src/libid3tag/compat.gperf300
-rw-r--r--src/libid3tag/compat.h41
-rw-r--r--src/libid3tag/config.h80
-rw-r--r--src/libid3tag/crc.c137
-rw-r--r--src/libid3tag/crc.h29
-rw-r--r--src/libid3tag/debug.c222
-rw-r--r--src/libid3tag/debug.h34
-rw-r--r--src/libid3tag/field.c906
-rw-r--r--src/libid3tag/field.h36
-rw-r--r--src/libid3tag/file.c843
-rw-r--r--src/libid3tag/file.h25
-rw-r--r--src/libid3tag/frame.c627
-rw-r--r--src/libid3tag/frame.h36
-rw-r--r--src/libid3tag/frametype.c568
-rw-r--r--src/libid3tag/frametype.gperf363
-rw-r--r--src/libid3tag/frametype.h42
-rw-r--r--src/libid3tag/genre.c151
-rw-r--r--src/libid3tag/genre.dat480
-rw-r--r--src/libid3tag/genre.dat.in180
-rw-r--r--src/libid3tag/genre.dat.sed54
-rw-r--r--src/libid3tag/genre.h27
-rw-r--r--src/libid3tag/global.h53
-rw-r--r--src/libid3tag/id3tag.h367
-rw-r--r--src/libid3tag/latin1.c217
-rw-r--r--src/libid3tag/latin1.h45
-rw-r--r--src/libid3tag/parse.c196
-rw-r--r--src/libid3tag/parse.h34
-rw-r--r--src/libid3tag/render.c200
-rw-r--r--src/libid3tag/render.h40
-rw-r--r--src/libid3tag/tag.c912
-rw-r--r--src/libid3tag/tag.h30
-rw-r--r--src/libid3tag/ucs4.c290
-rw-r--r--src/libid3tag/ucs4.h41
-rw-r--r--src/libid3tag/utf16.c286
-rw-r--r--src/libid3tag/utf16.h51
-rw-r--r--src/libid3tag/utf8.c365
-rw-r--r--src/libid3tag/utf8.h42
-rw-r--r--src/libid3tag/util.c147
-rw-r--r--src/libid3tag/util.h35
-rw-r--r--src/libid3tag/version.c45
-rw-r--r--src/libid3tag/version.h25
-rw-r--r--src/tests/Makefile54
-rw-r--r--src/tests/README11
-rw-r--r--src/tests/tag_wma_test.c98
-rw-r--r--src/tests/test_harness.c38
-rw-r--r--src/tests/test_wma1.wmabin48404 -> 0 bytes
-rw-r--r--src/tests/test_wma2.wmabin48444 -> 0 bytes
-rw-r--r--src/tests/tuple_formatter_functor_test.c71
-rw-r--r--src/tests/tuple_formatter_test.c186
162 files changed, 7665 insertions, 15187 deletions
diff --git a/src/Makefile b/src/Makefile
index 249cb5b..a6d4f2c 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,4 +1,4 @@
-SUBDIRS = libaudcore libguess libid3tag libaudtag audacious libaudgui tests
+SUBDIRS = libaudcore libaudgui libguess libaudtag audacious
include ../extra.mk
diff --git a/src/audacious/Makefile b/src/audacious/Makefile
index 680db2b..7b19c5c 100644
--- a/src/audacious/Makefile
+++ b/src/audacious/Makefile
@@ -3,16 +3,13 @@ include ../../extra.mk
SUBDIRS = ${INTL_OBJECTIVE}
PROG = audacious2${PROG_SUFFIX}
-SRCS = af_equalizer.c \
- auddrct.c \
+SRCS = auddrct.c \
audconfig.c \
- build_stamp.c \
chardet.c \
configdb.c \
credits.c \
effect.c \
equalizer.c \
- equalizer_flow.c \
equalizer_preset.c \
eventqueue.c \
fft.c \
@@ -34,16 +31,13 @@ SRCS = af_equalizer.c \
probe.c \
rcfile.c \
signals.c \
- ui_fileinfopopup.c \
ui_headless.c \
ui_plugin_menu.c \
ui_preferences.c \
util.c \
vis_runner.c \
visualization.c \
- sync-menu.c \
ui_albumart.c \
- ui_fileinfo.c \
ui_misc.c
ifeq ($(USE_DBUS),yes)
@@ -64,15 +58,11 @@ INCLUDES = auddrct.h \
hook.h \
interface.h \
main.h \
- output.h \
playback.h \
playlist_container.h \
plugin.h \
preferences.h \
- ui_fileinfopopup.h \
- ui_plugin_menu.h \
- ui_preferences.h \
- util.h
+ ui_plugin_menu.h
DATA = images/about-logo.png \
images/appearance.png \
@@ -96,7 +86,7 @@ DATA = images/about-logo.png \
ui/playlist.ui \
ui/carbon-menubar.ui
-CLEAN = build_stamp.c libaudacious.exe.a
+CLEAN = build_stamp.c dbus-client-bindings.h dbus-server-bindings.h
EXT_DEPS = ../libguess/libguess.a
ifeq ($(USE_EGGSM),yes)
@@ -131,10 +121,13 @@ CPPFLAGS += -DHAVE_CONFIG_H \
-I.. -I../.. \
-I./intl \
-I. \
- -I../libaudcore
+ -I../libaudcore \
+ -I../libaudtag
LIBS += ${LDADD} \
-L../libaudcore -laudcore \
+ -L../libaudgui -laudgui \
+ -L../libaudtag -laudtag \
${LIBINTL} \
../libguess/libguess.a \
${EGGSM_LIBS} \
@@ -151,7 +144,7 @@ LDFLAGS += ${PROG_IMPLIB_LDFLAGS} ${AUDLDFLAGS}
build_stamp.c:
echo "#include <glib.h>" > build_stamp.c ; \
if test -d ../../.hg ; then \
- revh=`hg tip --template 'const gchar *build_stamp = "#rev#:#node|short#";\n' 2>/dev/null`; \
+ revh=`hg tip --template 'const gchar *build_stamp = "{rev}:{node|short}";\n' 2>/dev/null`; \
[ -z "$$revh" ] || echo "$$revh" >> build_stamp.c; \
else \
echo "const gchar *build_stamp = \"UNSUPPORTED VERSION\";" >> build_stamp.c; \
@@ -176,7 +169,7 @@ dbus-client-bindings.h: ${DBUS_BINDINGS_SOURCES}
install-extra:
if test -h "${DESTDIR}${bindir}/audacious" ; then ${RM} "${DESTDIR}${bindir}/audacious" ; fi
- ${LN_S} "${DESTDIR}${bindir}/audacious2" "${DESTDIR}${bindir}/audacious"
+ ${LN_S} audacious2 "${DESTDIR}${bindir}/audacious"
if test x"${PROG_IMPLIB_NEEDED}" = x"yes"; then \
for i in ${PROG}; do \
diff --git a/src/audacious/af_compat.h b/src/audacious/af_compat.h
deleted file mode 100644
index e8f1fb6..0000000
--- a/src/audacious/af_compat.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * MPlayer libaf compatibility stuff
- */
-
-#ifndef AUDACIOUS_AF_COMPAT_H
-#define AUDACIOUS_AF_COMPAT_H
-
-#include <glib.h>
-#include "main.h"
-
-/* Number of channels */
-#ifndef AF_NCH
-#define AF_NCH 6
-#endif
-
-/* Format */
-#define AF_FORMAT_BE (0<<0) // Big Endian
-#define AF_FORMAT_LE (1<<0) // Little Endian
-#define AF_FORMAT_F (1<<2) // Foating point
-#define AF_FORMAT_32BIT (3<<3)
-#define AF_FORMAT_FLOAT_LE (AF_FORMAT_F|AF_FORMAT_32BIT|AF_FORMAT_LE)
-#define AF_FORMAT_FLOAT_BE (AF_FORMAT_F|AF_FORMAT_32BIT|AF_FORMAT_BE)
-
-#if G_BYTE_ORDER == G_BIG_ENDIAN // Native endian of cpu
-#define AF_FORMAT_FLOAT_NE AF_FORMAT_FLOAT_BE
-#else
-#define AF_FORMAT_FLOAT_NE AF_FORMAT_FLOAT_LE
-#endif
-
-#define AF_MSG_INFO 0 ///< Important information
-
-#define af_msg(a,...) AUDDBG(__VA_ARGS__);
-
-/* Control */
-#define AF_CONTROL_SET 0x00000000
-#define AF_CONTROL_GET 0x00000001
-
-#define AF_CONTROL_MANDATORY 0x10000000
-#define AF_CONTROL_OPTIONAL 0x20000000
-#define AF_CONTROL_FILTER_SPECIFIC 0x40000000
-
-#define AF_CONTROL_REINIT 0x00000100 | AF_CONTROL_MANDATORY
-#define AF_CONTROL_EQUALIZER_GAIN 0x00001C00 | AF_CONTROL_FILTER_SPECIFIC
-
-/* Return values */
-#define AF_DETACH 2
-#define AF_OK 1
-#define AF_TRUE 1
-#define AF_FALSE 0
-#define AF_UNKNOWN -1
-#define AF_ERROR -2
-#define AF_FATAL -3
-
-/* Audio data chunk */
-typedef struct af_data_s
-{
- void* audio; /* data buffer */
- int len; /* buffer length */
- int rate; /* sample rate */
- int nch; /* number of channels */
- int format; /* format */
- int bps; /* bytes per sample */
-} af_data_t;
-
-struct af_instance_s;
-/* Audio filter information not specific for current instance, but for
- a specific filter */
-typedef struct af_info_s
-{
- const char *info;
- const char *name;
- const char *author;
- const char *comment;
- const int flags;
- int (*open)(struct af_instance_s* vf);
-} af_info_t;
-
-/* Linked list of audio filters */
-typedef struct af_instance_s
-{
- af_info_t* info;
- int (*control)(struct af_instance_s* af, int cmd, void* arg);
- void (*uninit)(struct af_instance_s* af);
- af_data_t* (*play)(struct af_instance_s* af, af_data_t* data);
- void* setup; // setup data for this specific instance and filter
- af_data_t* data; // configuration for outgoing data stream
- struct af_instance_s* next;
- struct af_instance_s* prev;
- double delay; /* Delay caused by the filter, in units of bytes read without
- * corresponding output */
- double mul; /* length multiplier: how much does this instance change
- the length of the buffer. */
-}af_instance_t;
-
-/*********************************************
- Extended control used with arguments that operates on only one
- channel at the time
-*/
-typedef struct af_control_ext_s{
- void* arg; // Argument
- int ch; // Chanel number
-}af_control_ext_t;
-
-#endif /* AUDACIOUS_AF_COMPAT_H */
diff --git a/src/audacious/af_equalizer.c b/src/audacious/af_equalizer.c
deleted file mode 100644
index 71c78bf..0000000
--- a/src/audacious/af_equalizer.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*=============================================================================
-//
-// This software has been released under the terms of the GNU General Public
-// license. See http://www.gnu.org/copyleft/gpl.html for details.
-//
-// Copyright 2001 Anders Johansson ajh@atri.curtin.edu.au
-//
-//=============================================================================
-*/
-
-/* Equalizer filter, implementation of a 10 band time domain graphic
- equalizer using IIR filters. The IIR filters are implemented using a
- Direct Form II approach, but has been modified (b1 == 0 always) to
- save computation.
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <inttypes.h>
-#include <math.h>
-
-#include "af_compat.h"
-
-#define L 2 // Storage for filter taps
-#define KM 10 // Max number of bands
-
-#define Q 1.2247449
-/* Q value for band-pass filters 1.2247=(3/2)^(1/2)
- gives 4dB suppression @ Fc*2 and Fc/2 */
-
-/* Center frequencies for band-pass filters
- The different frequency bands are:
- nr. center frequency
- 0 31.25 Hz
- 1 62.50 Hz
- 2 125.0 Hz
- 3 250.0 Hz
- 4 500.0 Hz
- 5 1.000 kHz
- 6 2.000 kHz
- 7 4.000 kHz
- 8 8.000 kHz
- 9 16.00 kHz
-*/
-/*#define CF {31.25,62.5,125,250,500,1000,2000,4000,8000,16000}*/
-#define CF {60, 170, 310, 600, 1000, 3000, 6000, 12000, 14000, 16000}
-
-// Data for specific instances of this filter
-typedef struct af_equalizer_s
-{
- float a[KM][L]; // A weights
- float b[KM][L]; // B weights
- float wq[AF_NCH][KM][L]; // Circular buffer for W data
- float g[AF_NCH][KM]; // Gain factor for each channel and band
- int K; // Number of used eq bands
- int channels; // Number of channels
-} af_equalizer_t;
-
-static int af_test_output(struct af_instance_s* af, af_data_t* out)
-{
- if((af->data->format != out->format) ||
- (af->data->bps != out->bps) ||
- (af->data->rate != out->rate) ||
- (af->data->nch != out->nch)){
- memcpy(out,af->data,sizeof(af_data_t));
- return AF_FALSE;
- }
- return AF_OK;
-}
-
-// 2nd order Band-pass Filter design
-static void bp2(float* a, float* b, float fc, float q){
- double th= 2.0 * M_PI * fc;
- double C = (1.0 - tan(th*q/2.0))/(1.0 + tan(th*q/2.0));
-
- a[0] = (1.0 + C) * cos(th);
- a[1] = -1 * C;
-
- b[0] = (1.0 - C)/2.0;
- b[1] = -1.0050;
-}
-
-// Initialization and runtime control
-static int control(struct af_instance_s* af, int cmd, void* arg)
-{
- af_equalizer_t* s = (af_equalizer_t*)af->setup;
-
- switch(cmd){
- case AF_CONTROL_REINIT:{
- int k = 0;
- float F[KM] = CF;
-
- // Sanity check
- if(!arg) return AF_ERROR;
-
- af->data->rate = ((af_data_t*)arg)->rate;
- af->data->nch = ((af_data_t*)arg)->nch;
- af->data->format = AF_FORMAT_FLOAT_NE;
- af->data->bps = 4;
-
- // Calculate number of active filters
- s->K=KM;
- while(F[s->K-1] > (float)af->data->rate/2.2)
- s->K--;
-
- if(s->K != KM)
- af_msg(AF_MSG_INFO,"[equalizer] Limiting the number of filters to"
- " %i due to low sample rate.\n",s->K);
-
- // Generate filter taps
- for(k=0;k<s->K;k++)
- bp2(s->a[k],s->b[k],F[k]/((float)af->data->rate),Q);
-
- // Calculate how much this plugin adds to the overall time delay
- af->delay = 2 * af->data->nch * af->data->bps;
-
- return af_test_output(af,arg);
- }
- case AF_CONTROL_EQUALIZER_GAIN | AF_CONTROL_SET:{
- float* gain = ((af_control_ext_t*)arg)->arg;
- int ch = ((af_control_ext_t*)arg)->ch;
- int k;
- if(ch >= AF_NCH || ch < 0)
- return AF_ERROR;
-
- for(k = 0 ; k<KM ; k++)
- s->g[ch][k] = pow (10, gain[k] / 20) - 1;
-
- return AF_OK;
- }
- }
- return AF_UNKNOWN;
-}
-
-// Deallocate memory
-static void uninit(struct af_instance_s* af)
-{
- if(af->data)
- free(af->data);
- if(af->setup)
- free(af->setup);
-}
-
-// Filter data through filter
-static af_data_t* play(struct af_instance_s* af, af_data_t* data)
-{
- af_data_t* c = data; // Current working data
- af_equalizer_t* s = (af_equalizer_t*)af->setup; // Setup
- uint32_t ci = af->data->nch; // Index for channels
- uint32_t nch = af->data->nch; // Number of channels
-
- while(ci--){
- float* g = s->g[ci]; // Gain factor
- float* in = ((float*)c->audio)+ci;
- float* out = ((float*)c->audio)+ci;
- float* end = in + c->len/4; // Block loop end
-
- while(in < end){
- register int k = 0; // Frequency band index
- register float yt = *in; // Current input sample
- in+=nch;
-
- // Run the filters
- for(;k<s->K;k++){
- // Pointer to circular buffer wq
- register float* wq = s->wq[ci][k];
- // Calculate output from AR part of current filter
- register float w=yt*s->b[k][0] + wq[0]*s->a[k][0] + wq[1]*s->a[k][1];
- // Calculate output form MA part of current filter
- yt+=(w + wq[1]*s->b[k][1])*g[k];
- // Update circular buffer
- wq[1] = wq[0];
- wq[0] = w;
- }
- // Calculate output
- * out = yt;
- out+=nch;
- }
- }
- return c;
-}
-
-// Allocate memory and set function pointers
-int equalizer_open(af_instance_t* af){
- af->control=control;
- af->uninit=uninit;
- af->play=play;
- af->mul=1;
- af->data=calloc(1,sizeof(af_data_t));
- af->setup=calloc(1,sizeof(af_equalizer_t));
- if(af->data == NULL || af->setup == NULL)
- return AF_ERROR;
- return AF_OK;
-}
diff --git a/src/audacious/audconfig.c b/src/audacious/audconfig.c
index 9743374..47c376a 100644
--- a/src/audacious/audconfig.c
+++ b/src/audacious/audconfig.c
@@ -1,5 +1,5 @@
/* Audacious - Cross-platform multimedia player
- * Copyright (C) 2005-2008 Audacious development team.
+ * Copyright (C) 2005-2010 Audacious development team.
*
* Based on BMP:
* Copyright (C) 2003-2004 BMP development team.
@@ -31,9 +31,8 @@
#include "effect.h"
#include "general.h"
+#include "output.h"
#include "playback.h"
-#include "playlist-new.h"
-#include "playlist-utils.h"
#include "pluginenum.h"
#include "plugin-registry.h"
#include "util.h"
@@ -91,9 +90,17 @@ AudConfig aud_default_config = {
.replay_gain_preamp = 0,
.default_gain = 0,
.sw_volume_left = 100, .sw_volume_right = 100,
- .clear_playlist = FALSE,
+ .clear_playlist = TRUE,
.output_path = NULL,
.output_number = -1,
+
+ /* libaudgui stuff */
+ .no_confirm_playlist_delete = FALSE,
+ .playlist_manager_x = 0,
+ .playlist_manager_y = 0,
+ .playlist_manager_width = 0,
+ .playlist_manager_height = 0,
+ .playlist_manager_close_on_activate = FALSE,
};
typedef struct aud_cfg_boolent_t {
@@ -138,7 +145,10 @@ static aud_cfg_boolent aud_boolents[] = {
{"enable_clipping_prevention", &cfg.enable_clipping_prevention, TRUE},
{"replay_gain_track", &cfg.replay_gain_track, TRUE},
{"replay_gain_album", &cfg.replay_gain_album, TRUE},
- {"clear_playlist", & cfg.clear_playlist, TRUE},
+ {"clear_playlist", &cfg.clear_playlist, TRUE},
+ {"no_confirm_playlist_delete", &cfg.no_confirm_playlist_delete, TRUE},
+ {"playlist_manager_close_on_activate",
+ & cfg.playlist_manager_close_on_activate, TRUE},
};
static gint ncfgbent = G_N_ELEMENTS(aud_boolents);
@@ -155,6 +165,10 @@ static aud_cfg_nument aud_numents[] = {
{"sw_volume_left", & cfg.sw_volume_left, TRUE},
{"sw_volume_right", & cfg.sw_volume_right, TRUE},
{"output_number", & cfg.output_number, TRUE},
+ {"playlist_manager_x", & cfg.playlist_manager_x, TRUE},
+ {"playlist_manager_y", & cfg.playlist_manager_y, TRUE},
+ {"playlist_manager_width", & cfg.playlist_manager_width, TRUE},
+ {"playlist_manager_height", & cfg.playlist_manager_height, TRUE},
};
static gint ncfgient = G_N_ELEMENTS(aud_numents);
@@ -177,134 +191,6 @@ static aud_cfg_strent aud_strents[] = {
static gint ncfgsent = G_N_ELEMENTS(aud_strents);
-
-static gboolean
-save_extra_playlist(const gchar * path, const gchar * basename,
- gpointer savedlist)
-{
- gint playlists, playlist;
- GList **saved;
- int found;
- const gchar * filename;
-
- playlists = playlist_count ();
- saved = (GList **) savedlist;
-
- found = 0;
-
- for (playlist = 0; playlist < playlists; playlist ++)
- {
- if (g_list_find (* saved, GINT_TO_POINTER (playlist)) != NULL)
- continue;
-
- filename = playlist_get_filename (playlist);
-
- if (filename == NULL)
- continue;
-
- if (strcmp(filename, path) == 0) {
- /* Save playlist */
- playlist_save(playlist, path);
- * saved = g_list_prepend (* saved, GINT_TO_POINTER (playlist));
- found = 1;
- break;
- }
- }
-
- if(!found) {
- /* Remove playlist */
- unlink(path);
- }
-
- return FALSE; /* process other playlists */
-}
-
-static void
-save_other_playlists(GList *saved)
-{
- gint playlists, playlist;
- gchar * pos, * ext, * basename, * newbasename, * new_filename;
- const gchar * filename;
- int i, num, isdigits;
-
- playlists = playlist_count ();
-
- for (playlist = 0; playlist < playlists; playlist ++)
- {
- if (g_list_find (saved, GINT_TO_POINTER (playlist)) != NULL)
- continue;
-
- filename = playlist_get_filename (playlist);
-
- if (filename == NULL || g_file_test (filename, G_FILE_TEST_IS_DIR))
- {
- /* default basename */
-#ifdef HAVE_XSPF_PLAYLIST
- basename = g_strdup("playlist_01.xspf");
-#else
- basename = g_strdup("playlist_01.m3u");
-#endif
- } else {
- basename = g_path_get_basename(filename);
- }
-
- if ((pos = strrchr(basename, '.'))) {
- *pos = '\0';
- }
-#ifdef HAVE_XSPF_PLAYLIST
- ext = ".xspf";
-#else
- ext = ".m3u";
-#endif
- num = -1;
- if ((pos = strrchr(basename, '_'))) {
- isdigits = 0;
- for (i=1; pos[i]; i++) {
- if (!g_ascii_isdigit(pos[i])) {
- isdigits = 0;
- break;
- }
- isdigits = 1;
- }
- if (isdigits) {
- num = atoi(pos+1) + 1;
- *pos = '\0';
- }
- }
- /* attempt to generate unique filename */
- new_filename = NULL;
-
- do {
- g_free (new_filename);
-
- if (num < 0) {
- /* try saving without number first */
- newbasename = g_strdup_printf("%s%s", basename, ext);
- num = 1;
- } else {
- newbasename = g_strdup_printf("%s_%02d%s", basename, num, ext);
- num++;
- if (num < 0) {
- g_warning("Playlist number in filename overflowed."
- " Not saving playlist.\n");
- goto cleanup;
- }
- }
-
- new_filename = g_build_filename (aud_paths[BMP_PATH_PLAYLISTS_DIR],
- newbasename, NULL);
- g_free(newbasename);
- }
- while (g_file_test (new_filename, G_FILE_TEST_EXISTS));
-
- playlist_save (playlist, new_filename);
-cleanup:
- g_free (new_filename);
- g_free(basename);
- }
-}
-
-
void
aud_config_free(void)
{
@@ -397,26 +283,6 @@ aud_config_load(void)
cfg.cover_name_exclude = g_strdup("back");
}
-void save_all_playlists (void)
-{
- GList * saved;
-
- /* Main playlist becomes #0 at load, so save #0 as main. -jlindgren */
- if (! playlist_save (0, aud_paths[BMP_PATH_PLAYLIST_FILE]))
- g_warning ("Could not save main playlist\n");
-
- /* Save extra playlists that were loaded from PLAYLISTS_DIR */
- saved = g_list_append (NULL, GINT_TO_POINTER (0));
-
- if (! dir_foreach (aud_paths[BMP_PATH_PLAYLISTS_DIR], save_extra_playlist,
- & saved, NULL))
- g_warning ("Could not save extra playlists\n");
-
- /* Save other playlists to PLAYLISTS_DIR */
- save_other_playlists (saved);
- g_list_free (saved);
-}
-
static void save_output_path (void)
{
const gchar * path = NULL;
@@ -437,6 +303,8 @@ aud_config_save(void)
gint i;
mcs_handle_t *db;
+ hook_call ("config save", NULL);
+
cfg.resume_state = playback_get_playing () ? (playback_get_paused () ? 2 :
1) : 0;
cfg.resume_playback_on_startup_time = playback_get_playing () ?
@@ -458,8 +326,6 @@ aud_config_save(void)
aud_numents[i].ie_vname,
*aud_numents[i].ie_vloc);
- hook_call("config save", db);
-
for (i = 0; i < ncfgsent; ++i) {
if (aud_strents[i].se_wrt)
cfg_db_set_string(db, NULL,
@@ -519,6 +385,4 @@ aud_config_save(void)
}
cfg_db_close(db);
-
- save_all_playlists ();
}
diff --git a/src/audacious/audconfig.h b/src/audacious/audconfig.h
index d739769..6350974 100644
--- a/src/audacious/audconfig.h
+++ b/src/audacious/audconfig.h
@@ -1,5 +1,5 @@
/* Audacious - Cross-platform multimedia player
- * Copyright (C) 2005-2008 Audacious development team
+ * Copyright (C) 2005-2010 Audacious development team
*
* Based on BMP:
* Copyright (C) 2003-2004 BMP development team
@@ -76,6 +76,12 @@ struct _AudConfig {
gboolean clear_playlist;
gchar * output_path;
gint output_number;
+
+ /* libaudgui stuff */
+ gboolean no_confirm_playlist_delete;
+ gint playlist_manager_x, playlist_manager_y, playlist_manager_width,
+ playlist_manager_height;
+ gboolean playlist_manager_close_on_activate;
};
typedef struct _AudConfig AudConfig;
@@ -83,8 +89,6 @@ typedef struct _AudConfig AudConfig;
extern AudConfig cfg;
extern AudConfig aud_default_config;
-void save_all_playlists (void);
-
void aud_config_free(void);
void aud_config_load(void);
void aud_config_save(void);
diff --git a/src/audacious/build_stamp.h b/src/audacious/build_stamp.h
deleted file mode 100644
index 9aa3ca3..0000000
--- a/src/audacious/build_stamp.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef AUDACIOUS_BUILD_STAMP_H
-#define AUDACIOUS_BUILD_STAMP_H
-
-extern const char *build_stamp;
-
-#endif /* AUDACIOUS_BUILD_STAMP_H */
diff --git a/src/audacious/credits.c b/src/audacious/credits.c
index 52701ab..7f6b135 100644
--- a/src/audacious/credits.c
+++ b/src/audacious/credits.c
@@ -70,6 +70,7 @@ static const gchar *credit_text[] = {
"Matti Hämäläinen",
"Sascha Hlusiak",
"John Lindgren",
+ "Michał Lipski",
"Giacomo Lozito",
"Cristi Măgherușan",
"Boris Mikhaylov",
@@ -99,7 +100,6 @@ static const gchar *credit_text[] = {
"Jussi Judin",
"Teru KAMOGASHIRA",
"Chris Kehler",
- "Michał Lipski",
"Mark Loeser",
"Alex Maclean",
"Michael Hanselmann",
diff --git a/src/audacious/dbus.c b/src/audacious/dbus.c
index 87ecbf2..c75d7a6 100644
--- a/src/audacious/dbus.c
+++ b/src/audacious/dbus.c
@@ -1,7 +1,7 @@
/*
* Audacious: A cross-platform multimedia player
* Copyright (c) 2007 Ben Tucker
- * Copyright 2009 John Lindgren
+ * Copyright 2009-2010 Audacious development team
*
* 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
@@ -263,7 +263,7 @@ static void tuple_insert_to_hash_full(GHashTable * md, const Tuple * tuple,
{
GValue *value = tuple_value_to_gvalue(tuple, tuple_key);
if (value != NULL)
- g_hash_table_insert(md, g_strdup(key), value);
+ g_hash_table_insert (md, (void *) key, value);
}
static void tuple_insert_to_hash(GHashTable * md, const Tuple * tuple,
@@ -644,7 +644,6 @@ static void get_mpris_metadata(struct MprisMetadataRequest *request)
static gboolean set_shuffle_cb (void * shuffle)
{
cfg.shuffle = GPOINTER_TO_INT (shuffle);
- playlist_set_shuffle (cfg.shuffle);
event_queue ("toggle shuffle", NULL);
return FALSE;
}
@@ -1412,61 +1411,58 @@ gboolean audacious_rc_get_eq(RemoteObject * obj, gdouble * preamp, GArray ** ban
{
int i;
- *preamp = (gdouble) equalizer_get_preamp();
+ * preamp = cfg.equalizer_preamp;
*bands = g_array_sized_new(FALSE, FALSE, sizeof(gdouble), AUD_EQUALIZER_NBANDS);
for (i = 0; i < AUD_EQUALIZER_NBANDS; i++)
- {
- gdouble val = (gdouble) equalizer_get_band(i);
- g_array_append_val(*bands, val);
- }
+ g_array_append_val (* bands, cfg.equalizer_bands[i]);
return TRUE;
}
gboolean audacious_rc_get_eq_preamp(RemoteObject * obj, gdouble * preamp, GError ** error)
{
- *preamp = (gdouble) equalizer_get_preamp();
+ * preamp = cfg.equalizer_preamp;
return TRUE;
}
gboolean audacious_rc_get_eq_band(RemoteObject * obj, gint band, gdouble * value, GError ** error)
{
- *value = (gdouble) equalizer_get_band(band);
+ * value = cfg.equalizer_bands[band];
return TRUE;
}
gboolean audacious_rc_set_eq(RemoteObject * obj, gdouble preamp, GArray * bands, GError ** error)
{
- gdouble element;
int i;
- equalizer_set_preamp((gfloat) preamp);
+ cfg.equalizer_preamp = preamp;
for (i = 0; i < AUD_EQUALIZER_NBANDS; i++)
- {
- element = g_array_index(bands, gdouble, i);
- equalizer_set_band(i, (gfloat) element);
- }
+ cfg.equalizer_bands[i] = g_array_index (bands, gdouble, i);
+ hook_call ("equalizer changed", NULL);
return TRUE;
}
gboolean audacious_rc_set_eq_preamp(RemoteObject * obj, gdouble preamp, GError ** error)
{
- equalizer_set_preamp((gfloat) preamp);
+ cfg.equalizer_preamp = preamp;
+ hook_call ("equalizer changed", NULL);
return TRUE;
}
gboolean audacious_rc_set_eq_band(RemoteObject * obj, gint band, gdouble value, GError ** error)
{
- equalizer_set_band(band, (gfloat) value);
+ cfg.equalizer_bands[band] = value;
+ hook_call ("equalizer changed", NULL);
return TRUE;
}
gboolean audacious_rc_equalizer_activate(RemoteObject * obj, gboolean active, GError ** error)
{
- equalizer_set_active(active);
+ cfg.equalizer_active = active;
+ hook_call ("equalizer changed", NULL);
return TRUE;
}
diff --git a/src/audacious/effect.c b/src/audacious/effect.c
index 2f15d68..03ad53f 100644
--- a/src/audacious/effect.c
+++ b/src/audacious/effect.c
@@ -199,21 +199,27 @@ static GList * new_effect_list = NULL;
void new_effect_start (gint * channels, gint * rate)
{
+ gint order;
GList * node;
EffectPlugin * effect;
g_list_free (new_effect_list);
new_effect_list = NULL;
- /* FIXME: Let the user define in what order the effects are applied. */
- for (node = ep_data.enabled_list; node != NULL; node = node->next)
+ for (order = 0; order < 10; order ++)
{
- effect = node->data;
+ for (node = ep_data.enabled_list; node != NULL; node = node->next)
+ {
+ effect = node->data;
+
+ if (effect->order != order)
+ continue;
- if (effect->start != NULL)
- new_effect_list = g_list_prepend (new_effect_list, effect);
- else
- printf ("Please update %s to new API.\n", effect->description);
+ if (effect->start != NULL)
+ new_effect_list = g_list_prepend (new_effect_list, effect);
+ else
+ printf ("Please update %s to new API.\n", effect->description);
+ }
}
new_effect_list = g_list_reverse (new_effect_list);
diff --git a/src/audacious/effect.h b/src/audacious/effect.h
index c8a6408..cc95c24 100644
--- a/src/audacious/effect.h
+++ b/src/audacious/effect.h
@@ -28,8 +28,7 @@
#include <glib.h>
-#include "audacious/flow.h"
-#include "audacious/output.h"
+#include "audacious/plugin.h"
typedef struct _EffectPluginData EffectPluginData;
diff --git a/src/audacious/equalizer.c b/src/audacious/equalizer.c
index cfd002c..6503762 100644
--- a/src/audacious/equalizer.c
+++ b/src/audacious/equalizer.c
@@ -1,77 +1,159 @@
-/* Audacious - Cross-platform multimedia player
- * Copyright (C) 2005-2008 Audacious development team.
+/*
+ * Equalizer filter, implementation of a 10 band time domain graphic equalizer
+ * using IIR filters. The IIR filters are implemented using a Direct Form II
+ * approach, modified (b1 == 0 always) to save computation.
*
- * 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; under version 3 of the License.
+ * This software has been released under the terms of the GNU General Public
+ * license. See http://www.gnu.org/copyleft/gpl.html for details.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * Copyright 2001 Anders Johansson <ajh@atri.curtin.edu.au>
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses>.
- *
- * The Audacious team does not consider modular code linking to
- * Audacious or using our public API to be a derived work.
+ * Adapted for Audacious by John Lindgren, 2010
*/
-#ifdef _AUDACIOUS_CORE
-# include "config.h"
-#endif
+#include <glib.h>
+#include <math.h>
+#include <string.h>
+#include "audconfig.h"
#include "equalizer.h"
-#include "equalizer_flow.h"
#include "hook.h"
-#include "output.h"
-#include "audconfig.h"
-static void eq_update (void * hook_data, void * user_data)
-{
- equalizer_flow_set_bands (cfg.equalizer_preamp, cfg.equalizer_bands);
-}
+#define EQ_BANDS AUD_EQUALIZER_NBANDS
+#define MAX_CHANNELS 10
-void init_equalizer (void)
+/* Q value for band-pass filters 1.2247 = (3/2)^(1/2)
+ * Gives 4 dB suppression at Fc*2 and Fc/2 */
+#define Q 1.2247449
+
+/* Center frequencies for band-pass filters (Hz) */
+static const gfloat CF[EQ_BANDS] = {60, 170, 310, 600, 1000, 3000, 6000, 12000,
+ 14000, 16000};
+
+static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
+static gboolean active;
+static gint channels, rate;
+static gfloat a[EQ_BANDS][2]; /* A weights */
+static gfloat b[EQ_BANDS][2]; /* B weights */
+static gfloat wqv[MAX_CHANNELS][EQ_BANDS][2]; /* Circular buffer for W data */
+static gfloat gv[MAX_CHANNELS][EQ_BANDS]; /* Gain factor for each channel and band */
+static gint K; /* Number of used eq bands */
+
+/* 2nd order band-pass filter design */
+static void bp2 (gfloat * a, gfloat * b, gfloat fc, gfloat q)
{
- hook_associate ("equalizer changed", eq_update, NULL);
- eq_update (NULL, NULL);
+ gfloat th = 2 * M_PI * fc;
+ gfloat C = (1 - tanf (th * q / 2)) / (1 + tanf (th * q / 2));
+
+ a[0] = (1 + C) * cosf (th);
+ a[1] = -C;
+ b[0] = (1 - C) / 2;
+ b[1] = -1.005;
}
-gfloat
-equalizer_get_preamp(void)
+void eq_set_format (gint new_channels, gint new_rate)
{
- return cfg.equalizer_preamp;
+ gint k;
+
+ g_static_mutex_lock (& mutex);
+
+ channels = new_channels;
+ rate = new_rate;
+
+ /* Calculate number of active filters */
+ K = EQ_BANDS;
+
+ while (CF[K - 1] > (gfloat) rate / 2.2)
+ K --;
+
+ /* Generate filter taps */
+ for (k = 0; k < K; k ++)
+ bp2 (a[k], b[k], CF[k] / (gfloat) rate, Q);
+
+ /* Reset state */
+ memset (wqv[0][0], 0, sizeof wqv);
+
+ g_static_mutex_unlock (& mutex);
}
-void
-equalizer_set_preamp(gfloat preamp)
+static void eq_set_channel_bands (gint channel, gfloat * bands)
{
- cfg.equalizer_preamp = preamp;
- eq_update (NULL, NULL);
+ gint k;
+
+ for (k = 0; k < EQ_BANDS; k ++)
+ gv[channel][k] = pow (10, bands[k] / 20) - 1;
}
-gfloat
-equalizer_get_band(gint band)
+static void eq_set_bands (gfloat preamp, gfloat * bands)
{
- return cfg.equalizer_bands[band];
+ gfloat adjusted[EQ_BANDS];
+ gint i;
+
+ for (i = 0; i < EQ_BANDS; i ++)
+ adjusted[i] = preamp + bands[i];
+
+ for (i = 0; i < MAX_CHANNELS; i ++)
+ eq_set_channel_bands (i, adjusted);
}
-void
-equalizer_set_band(gint band, gfloat value)
+void eq_filter (gfloat * data, gint samples)
{
- cfg.equalizer_bands[band] = value;
- eq_update (NULL, NULL);
+ gint channel;
+
+ g_static_mutex_lock (& mutex);
+
+ if (! active)
+ {
+ g_static_mutex_unlock (& mutex);
+ return;
+ }
+
+ for (channel = 0; channel < channels; channel ++)
+ {
+ gfloat * g = gv[channel]; /* Gain factor */
+ gfloat * end = data + samples;
+ gfloat * f;
+
+ for (f = data + channel; f < end; f += channels)
+ {
+ gint k; /* Frequency band index */
+ gfloat yt = * f; /* Current input sample */
+
+ for (k = 0; k < K; k ++)
+ {
+ /* Pointer to circular buffer wq */
+ gfloat * wq = wqv[channel][k];
+ /* Calculate output from AR part of current filter */
+ gfloat w = yt * b[k][0] + wq[0] * a[k][0] + wq[1] * a[k][1];
+
+ /* Calculate output from MA part of current filter */
+ yt += (w + wq[1] * b[k][1]) * g[k];
+
+ /* Update circular buffer */
+ wq[1] = wq[0];
+ wq[0] = w;
+ }
+
+ /* Calculate output */
+ * f = yt;
+ }
+ }
+
+ g_static_mutex_unlock (& mutex);
}
-gboolean equalizer_get_active(gboolean active)
+static void eq_update (void * data, void * user_data)
{
- return cfg.equalizer_active;
+ g_static_mutex_lock (& mutex);
+
+ active = cfg.equalizer_active;
+ eq_set_bands (cfg.equalizer_preamp, cfg.equalizer_bands);
+
+ g_static_mutex_unlock (& mutex);
}
-void
-equalizer_set_active(gboolean active)
+void eq_init (void)
{
- cfg.equalizer_active = active;
eq_update (NULL, NULL);
+ hook_associate ("equalizer changed", eq_update, NULL);
}
diff --git a/src/audacious/equalizer.h b/src/audacious/equalizer.h
index aba93d9..68ec61f 100644
--- a/src/audacious/equalizer.h
+++ b/src/audacious/equalizer.h
@@ -1,35 +1,29 @@
-/* Audacious - Cross-platform multimedia player
- * Copyright (C) 2005-2008 Audacious development team.
+/*
+ * equalizer.h
+ * Copyright 2010 John Lindgren
*
- * 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; under version 3 of the License.
+ * This file is part of Audacious.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * Audacious 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, version 2 or version 3 of the License.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses>.
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
- * The Audacious team does not consider modular code linking to
- * Audacious or using our public API to be a derived work.
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
*/
#ifndef AUDACIOUS_EQUALIZER_H
#define AUDACIOUS_EQUALIZER_H
-#include <glib.h>
-
-void init_equalizer (void);
-
-gfloat equalizer_get_preamp(void);
-void equalizer_set_preamp(gfloat preamp);
-gfloat equalizer_get_band(gint band);
-void equalizer_set_band(gint band, gfloat value);
-
-gboolean equalizer_get_active();
-void equalizer_set_active(gboolean active);
+void eq_init (void);
+void eq_set_format (gint new_channels, gint new_rate);
+void eq_filter (gfloat * data, gint samples);
#endif
diff --git a/src/audacious/equalizer_flow.c b/src/audacious/equalizer_flow.c
deleted file mode 100644
index f5c6395..0000000
--- a/src/audacious/equalizer_flow.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/* Audacious - Cross-platform multimedia player
- * Copyright (C) 2005-2008 Audacious team
- *
- * 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; under version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses>.
- *
- * The Audacious team does not consider modular code linking to
- * Audacious or using our public API to be a derived work.
- */
-
-#include <glib.h>
-#include <math.h>
-#include "main.h"
-#include "plugin.h"
-#include "flow.h"
-
-#include "af_compat.h"
-#include "equalizer_flow.h"
-
-int equalizer_open(af_instance_t* af); /* af_equalizer.c */
-
-static af_instance_t *eq = NULL;
-static gint eq_nch = 0;
-static gint eq_rate = 0;
-static gboolean bands_changed = FALSE;
-
-static void
-equalizer_flow_reinit(gint rate, gint nch)
-{
- af_data_t data;
-
- if(eq == NULL) return;
-
- data.rate = rate;
- data.nch = nch;
- data.bps = 4;
- data.format = AF_FORMAT_FLOAT_NE;
- eq->control(eq, AF_CONTROL_REINIT, &data);
-}
-
-void
-equalizer_flow(FlowContext *context)
-{
- af_data_t data;
-
- if(!cfg.equalizer_active || eq == NULL) return;
-
- if(context->fmt != FMT_FLOAT) {
- context->error = TRUE;
- return;
- }
-
- if(eq_nch != context->channels ||
- eq_rate != context->srate ||
- bands_changed) {
- equalizer_flow_reinit(context->srate, context->channels);
- eq_nch = context->channels;
- eq_rate = context->srate;
- bands_changed = FALSE;
- }
-
- data.nch = context->channels;
- data.audio = context->data;
- data.len = context->len;
- eq->play(eq, &data);
-}
-
-void
-equalizer_flow_set_bands(gfloat pre, gfloat *bands)
-{
- int i;
- af_control_ext_t ctl;
- float adjusted [10]; /* ctl.arg is (float *), not (gfloat *) */
-
- if(eq == NULL) {
- eq = g_malloc(sizeof(af_instance_t));
- equalizer_open(eq);
- }
-
- for (i = 0; i < 10; i ++)
- adjusted[i] = (bands[i] + pre);
-
- ctl.arg = adjusted;
- for (i = 0; i < AF_NCH; i++) {
- ctl.ch = i;
- eq->control(eq, AF_CONTROL_EQUALIZER_GAIN | AF_CONTROL_SET, &ctl);
- }
-
- bands_changed = TRUE;
-}
-
-void
-equalizer_flow_free()
-{
- AUDDBG("\n");
- if(eq != NULL) {
- eq->uninit(eq);
- g_free(eq);
- eq = NULL;
- eq_nch = 0;
- eq_rate = 0;
- bands_changed = FALSE;
- }
-}
diff --git a/src/audacious/equalizer_flow.h b/src/audacious/equalizer_flow.h
deleted file mode 100644
index 9b298f0..0000000
--- a/src/audacious/equalizer_flow.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef AUDACIOUS_EQUALIZER_FLOW_H
-#define AUDACIOUS_EQUALIZER_FLOW_H
-
-#include "flow.h"
-
-#define EQUALIZER_MAX_GAIN 12.0
-
-void equalizer_flow(FlowContext *context);
-void equalizer_flow_set_bands(gfloat pre, gfloat *bands);
-void equalizer_flow_free();
-
-#endif /* AUDACIOUS_EQUALIZER_FLOW_H */
diff --git a/src/audacious/equalizer_preset.c b/src/audacious/equalizer_preset.c
index 18652b8..60ecdba 100644
--- a/src/audacious/equalizer_preset.c
+++ b/src/audacious/equalizer_preset.c
@@ -26,8 +26,8 @@
#include "main.h"
#include "plugin.h"
#include "rcfile.h"
+#include "equalizer.h"
#include "equalizer_preset.h"
-#include "equalizer_flow.h"
EqualizerPreset *
equalizer_preset_new(const gchar * name)
diff --git a/src/audacious/flow.h b/src/audacious/flow.h
index d66a4ba..f5b9963 100644
--- a/src/audacious/flow.h
+++ b/src/audacious/flow.h
@@ -20,13 +20,13 @@
* Audacious or using our public API to be a derived work.
*/
+#ifndef AUDACIOUS_FLOW_H
+#define AUDACIOUS_FLOW_H
+
#include <glib.h>
#include <mowgli.h>
-#include "output.h"
-
-#ifndef AUDACIOUS_FLOW_H
-#define AUDACIOUS_FLOW_H
+#include <libaudcore/audio.h>
typedef struct {
gint time;
diff --git a/src/audacious/folder-add.c b/src/audacious/folder-add.c
index 30308af..f6ae0d0 100644
--- a/src/audacious/folder-add.c
+++ b/src/audacious/folder-add.c
@@ -83,11 +83,6 @@ static void show_done (void)
gtk_widget_destroy (add_window);
}
-static gint compare (const void * * a, const void * * b)
-{
- return string_compare (* (const gchar * *) a, * (const gchar * *) b);
-}
-
static gboolean add_cb (void * unused)
{
static GList * stack = NULL;
@@ -113,7 +108,8 @@ static gboolean add_cb (void * unused)
{
gchar * filename = g_filename_to_uri (stack->data, NULL, NULL);
- if (filename != NULL && file_probe (filename, TRUE) != NULL)
+ if (filename != NULL && file_find_decoder (filename, TRUE) !=
+ NULL)
index_append (index, filename);
else
g_free (filename);
@@ -159,7 +155,8 @@ static gboolean add_cb (void * unused)
if (stack == NULL)
{
- index_sort (index, compare);
+ index_sort (index, (gint (*) (const void *, const void *))
+ string_compare);
count = playlist_count ();
@@ -180,7 +177,7 @@ static gboolean add_cb (void * unused)
if (add_at > 0)
playlist_set_position (add_playlist, add_at);
-
+
playback_initiate ();
}
diff --git a/src/audacious/images/audacious_player.xpm b/src/audacious/images/audacious_player.xpm
index ef31506..f850210 100644
--- a/src/audacious/images/audacious_player.xpm
+++ b/src/audacious/images/audacious_player.xpm
@@ -1,221 +1,165 @@
/* XPM */
static char * audacious_player_xpm[] = {
-"48 48 170 2",
+"48 48 114 2",
" c None",
-". c #EBEBEB",
-"+ c #E4E4E4",
-"@ c #DDDDDD",
-"# c #D6D6D6",
-"$ c #D0D0D0",
-"% c #CCCCCC",
-"& c #EAEAEA",
-"* c #CDCDCD",
-"= c #BBBBBB",
-"- c #AAAAAA",
-"; c #9D9D9D",
-"> c #939393",
-", c #8A8A8A",
-"' c #858585",
-") c #E8E8E8",
-"! c #D3D3D3",
-"~ c #A0A0A0",
-"{ c #878787",
-"] c #6E6E6E",
-"^ c #5A5A5A",
-"/ c #4D4D4D",
-"( c #454545",
-"_ c #3E3E3E",
-": c #3B3B3B",
-"< c #ECECEC",
-"[ c #D7D7D7",
-"} c #B9B9B9",
-"| c #949494",
-"1 c #707070",
-"2 c #535353",
-"3 c #3D3D3D",
-"4 c #2B2B2B",
-"5 c #1E1E1E",
-"6 c #171717",
-"7 c #131313",
-"8 c #111111",
-"9 c #101010",
-"0 c #C4C4C4",
-"a c #9C9C9C",
-"b c #717171",
-"c c #4B4B4B",
-"d c #2E2E2E",
-"e c #1C1C1C",
-"f c #0A0A0A",
-"g c #060606",
-"h c #040404",
-"i c #030303",
-"j c #B7B7B7",
-"k c #555555",
-"l c #313131",
-"m c #1A1A1A",
-"n c #0C0C0C",
-"o c #020202",
-"p c #050505",
-"q c #080808",
-"r c #0B0B0B",
-"s c #D8D8D8",
-"t c #ADADAD",
-"u c #777777",
-"v c #444444",
-"w c #212121",
+". c #000000",
+"+ c #202020",
+"@ c #5E5E5E",
+"# c #909090",
+"$ c #B1B1B1",
+"% c #CACACA",
+"& c #D5D5D5",
+"* c #B0B0B0",
+"= c #8E8E8E",
+"- c #5A5A5A",
+"; c #1D1D1D",
+"> c #030303",
+", c #4D4D4D",
+"' c #A8A8A8",
+") c #D9D9D9",
+"! c #D8D8D8",
+"~ c #A4A4A4",
+"{ c #484848",
+"] c #020202",
+"^ c #3C3C3C",
+"/ c #B8B8B8",
+"( c #B5B5B5",
+"_ c #393939",
+": c #090909",
+"< c #858585",
+"[ c #828282",
+"} c #070707",
+"| c #141414",
+"1 c #AEAEAE",
+"2 c #ADADAD",
+"3 c #121212",
+"4 c #B9B9B9",
+"5 c #ABABAB",
+"6 c #AAAAAA",
+"7 c #080808",
+"8 c #D0D0D0",
+"9 c #BCBCBC",
+"0 c #CBCBCB",
+"a c #818181",
+"b c #3A3A3A",
+"c c #8C8C8C",
+"d c #535353",
+"e c #414141",
+"f c #2D2D2D",
+"g c #010101",
+"h c #161616",
+"i c #4E4E4E",
+"j c #9E9E9E",
+"k c #373737",
+"l c #B6B6B6",
+"m c #313131",
+"n c #B4B4B4",
+"o c #9A9A9A",
+"p c #0C0C0C",
+"q c #474747",
+"r c #A6A6A6",
+"s c #939393",
+"t c #282828",
+"u c #A5A5A5",
+"v c #1F1F1F",
+"w c #D6D6D6",
"x c #0E0E0E",
-"y c #070707",
-"z c #2C2C2C",
-"A c #363636",
-"B c #434343",
-"C c #D9D9D9",
-"D c #A9A9A9",
-"E c #6D6D6D",
-"F c #191919",
-"G c #090909",
-"H c #2F2F2F",
-"I c #696969",
-"J c #888888",
-"K c #A6A6A6",
-"L c #B5B5B5",
-"M c #BABABA",
-"N c #DEDEDE",
-"O c #AEAEAE",
-"P c #161616",
-"Q c #121212",
-"R c #585858",
-"S c #D1D1D1",
-"T c #898989",
-"U c #E5E5E5",
-"V c #B8B8B8",
-"W c #767676",
-"X c #3A3A3A",
-"Y c #151515",
-"Z c #464646",
-"` c #808080",
-" . c #C0C0C0",
-".. c #BFBFBF",
-"+. c #C7C7C7",
-"@. c #A1A1A1",
-"#. c #D5D5D5",
-"$. c #DADADA",
-"%. c #545454",
-"&. c #1F1F1F",
-"*. c #202020",
-"=. c #5C5C5C",
-"-. c #B1B1B1",
-";. c #0D0D0D",
-">. c #B2B2B2",
-",. c #969696",
-"'. c #494949",
-"). c #A2A2A2",
-"!. c #A3A3A3",
-"~. c #818181",
-"{. c #C5C5C5",
-"]. c #474747",
-"^. c #C6C6C6",
-"/. c #E1E1E1",
-"(. c #505050",
-"_. c #181818",
-":. c #141414",
-"<. c #575757",
-"[. c #C2C2C2",
-"}. c #000000",
-"|. c #515151",
-"1. c #D2D2D2",
-"2. c #383838",
-"3. c #A7A7A7",
-"4. c #262626",
-"5. c #484848",
-"6. c #BCBCBC",
-"7. c #9A9A9A",
-"8. c #393939",
-"9. c #BDBDBD",
-"0. c #E9E9E9",
-"a. c #AFAFAF",
-"b. c #1B1B1B",
-"c. c #5F5F5F",
-"d. c #E2E2E2",
-"e. c #272727",
-"f. c #8E8E8E",
-"g. c #333333",
-"h. c #8C8C8C",
-"i. c #DBDBDB",
-"j. c #959595",
-"k. c #404040",
-"l. c #010101",
-"m. c #303030",
-"n. c #ACACAC",
-"o. c #ABABAB",
-"p. c #7B7B7B",
-"q. c #373737",
-"r. c #606060",
-"s. c #919191",
-"t. c #424242",
-"u. c #7C7C7C",
-"v. c #A5A5A5",
-"w. c #353535",
-"x. c #525252",
-"y. c #343434",
-"z. c #D4D4D4",
-"A. c #666666",
-"B. c #7E7E7E",
-"C. c #C1C1C1",
-"D. c #C9C9C9",
-"E. c #8F8F8F",
-"F. c #3F3F3F",
-"G. c #CACACA",
-"H. c #757575",
-"I. c #636363",
-"J. c #C8C8C8",
-"K. c #848484",
-"L. c #A8A8A8",
-"M. c #929292",
-" ",
-" . + @ # $ % % $ # @ + . ",
-" & @ * = - ; > , ' ' , > ; - = * @ & ",
-" ) ! = ~ { ] ^ / ( _ : : _ ( / ^ ] { ~ = ! ) ",
-" < [ } | 1 2 3 4 5 6 7 8 9 9 8 7 6 5 4 3 2 1 | } [ < ",
-" + 0 a b c d e 8 f g h i i i i i i h g f 8 e d c b a 0 + ",
-" @ j ' k l m n g i o h p g q r r q g p h o i g n m l k ' j @ ",
-" s t u v w x g i i y 9 5 z A 3 B B 3 A z 5 9 y i i g x w v u t s ",
-" C D E : F G i i q 6 H c I J K L M M L K J I c H 6 q i i G F : E D C ",
-" N O ] A P y o h Q d R , M S C s C C C C s C S M T R d Q h o y P A ] O N ",
-" U V W X Y g o g m Z ` .s C C C s C C C C s C C C s ..` Z m g o g Y X W V U ",
-" +.' B F g o y w k @.#.C C $.C C C C C C C C C C $.C C #.@.k w y o g F B ' +. ",
-" $.; %.&.q o g *.=.-.s $.$.C s C C C C C C C C C C s C $.$.s -.=.*.g o q &.%.; $. ",
-" . = b H ;.o h m %.>.C C $.C C C C $.C s C C s C $.C C C C $.C C -.%.m h o ;.H b = . ",
-" s ,.'.6 p o 9 ( ).s $.C C C $.C C C C C C C C C C C C $.C C C $.s !.( 9 o p 6 '.,.s ",
-" ..1 4 f o g z ~.#.$.$.C C C C C {.!.| ] / ].^ ' ^.C C C C C C $.$.#.~.z g o f 4 1 .. ",
-" /.!.(._.h i :.<.[.C C C C C C C u i }.}.}.}.}.}.}.i |.{.C C C C C C C [.<.:.i h _.(.!./. ",
-" 1.{ 2.x o p 4 , [ C C $.C s C 3.}.}.}.}.}.}.}.}.}.}.}.:.M C s C $.C C [ , 4 p o x 2.{ 1. ",
-" .E 4.q o x 5.6.C s s C C C C 7.}.}.}.}.}.}.}.}.}.}.}.}.8.C C C C s s C 9.5.x o q 4.E . ",
-" 0.a.<.F h o b.I ! C s s C C C C C b _ ^ c.c.(.h }.}.}.}.}.}.6.C C C s s C ! I b.o h F <.a.0. ",
-" d.@.'.Q o i e.f.C C s s $.C C C C C C C C C s g.}.}.}.}.}.}.h.C C $.s s C C f.e.i o Q '.@.d. ",
-" i.j.k.x l.h m.n.C C C C C C C C C C # o.p.q.8 }.}.}.}.}.}.}.r.C C C C C C C o.m.h l.x k.j.i. ",
-" # h.X ;.l.g 2.= C C C C C C C C C s.Q }.}.}.}.}.}.}.}.}.}.}.t.C C C C C C C M 2.g l.;.X h.# ",
-" 1.{ A n l.q _ ..C C s $.C C C C u.}.}.}.}.}.}.}.}.}.}.}.}.}.3 C C C $.s C C ._ q l.n A { 1. ",
-" 1.{ A n l.q _ .C C s $.C C C v.o }.}.}.}.}.}.}.}.}.}.}.}.}.E C C C $.s C C ._ q l.n A { 1. ",
-" # h.X ;.l.g 2.= C C C C C C C w.}.}.}.}.}.z M M &.}.}.}.}.}.{ C C C C C C C = 2.g l.;.X h.# ",
-" i.j.k.x l.h m.t C C C C C C C 4 }.}.}.}.}.x.C [ e.}.}.}.}.}.).C C C C C C C t m.h l.x k.j.i. ",
-" d.@.'.Q o i e.s.C C s s $.C C m.}.}.}.}.}.i 8.y.}.}.}.}.}.}.D C C $.s s C C s.e.i o Q '.@.d. ",
-" 0.a.<.F h o b.I z.C s s C C C A.}.}.}.}.}.}.}.}.}.}.}.}.}.}.` C C C s s C #.I b.o h F <.a.0. ",
-" .E 4.q o x 5. .C s s C C C = g }.}.}.}.}.}.}.}.}.}.}.}.}.B.C C C s s C C.5.x o q 4.E . ",
-" 1.{ 2.x o p 4 f.s C C $.C s C ,.r }.}.}.}.}.i w G }.}.}.b.D.s C $.C C s E.4 p o x 2.{ 1. ",
-" /.!.(._.h i :.<.^.C C C C C C C M Z y }.F.j.$ C G.H.v I.J.C C C C C C {.<.:.i h _.(.!./. ",
-" ..1 4 f o g z K.# $.$.C C C C C C $ 0 C C C C C C C C C C C C $.$.# K.z g o f 4 1 .. ",
-" s ,.'.6 p o 9 ( L.C $.C C C $.C C C C C C C C C C C C $.C C C $.C L.( 9 o p 6 '.,.s ",
-" . = b H ;.o h m %.V C C $.C C C C $.C s C C s C $.C C C C $.C C j %.m h o ;.H b = . ",
-" $.; %.&.q o g *.=.} s $.$.C s C C C C C C C C C C s C $.$.s V =.*.g o q &.%.; $. ",
-" +.' B F g o y w k L.[ C C $.C C C C C C C C C C $.C C [ L.k w y o g F B ' +. ",
-" U V W X Y g o g m Z ' ^.C C C C s C C C C s C C C C ^.K.Z m g o g Y X W V U ",
-" N O ] A P y o h Q d R s.C.#.C s C C C C s C #. .E.R d Q h o y P A ] O N ",
-" C D E : F G i i q 6 H c I M.t = . .= t s.I c H 6 q i i G F : E D C ",
-" s t u v w x g i i y 9 5 z A 3 B B 3 A z 5 9 y i i g x w v u t s ",
-" @ j ' k l m n g i o h p g q r r q g p h o i g n m l k ' j @ ",
-" + 0 a b c d e 8 f g h i i i i i i h g f 8 e d c b a 0 + ",
-" < [ } | 1 2 3 4 5 6 7 8 9 9 8 7 6 5 4 3 2 1 | } [ < ",
-" ) ! = ~ { ] ^ / ( _ : : _ ( / ^ ] { ~ = ! ) ",
-" & @ * = - ; > , ' ' , > ; - = * @ & ",
-" . + @ # $ % % $ # @ + . ",
-" "};
+"y c #2B2B2B",
+"z c #1B1B1B",
+"A c #A9A9A9",
+"B c #1C1C1C",
+"C c #5B5B5B",
+"D c #464646",
+"E c #777777",
+"F c #595959",
+"G c #8D8D8D",
+"H c #CFCFCF",
+"I c #929292",
+"J c #6D6D6D",
+"K c #111111",
+"L c #494949",
+"M c #5D5D5D",
+"N c #353535",
+"O c #242424",
+"P c #757575",
+"Q c #C9C9C9",
+"R c #D4D4D4",
+"S c #404040",
+"T c #D3D3D3",
+"U c #ACACAC",
+"V c #B2B2B2",
+"W c #CCCCCC",
+"X c #646464",
+"Y c #737373",
+"Z c #A3A3A3",
+"` c #131313",
+" . c #8B8B8B",
+".. c #7B7B7B",
+"+. c #212121",
+"@. c #505050",
+"#. c #1E1E1E",
+"$. c #050505",
+"%. c #5C5C5C",
+"&. c #969696",
+"*. c #191919",
+"=. c #101010",
+"-. c #BDBDBD",
+";. c #B7B7B7",
+">. c #878787",
+",. c #898989",
+"'. c #343434",
+"). c #1A1A1A",
+"!. c #BBBBBB",
+"~. c #3B3B3B",
+"{. c #C2C2C2",
+"]. c #838383",
+"^. c #808080",
+"/. c #AFAFAF",
+" . . . . . . . . . . ",
+" . . . . . . . . . . . . . . . . ",
+" . . . . . . . . . . . . . . . . . . . . . . ",
+" . . . . . . . . . . . . . . . . . . . . . . . . ",
+" . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+" . . . . . . . . . . + @ # $ % & & % * = - ; . . . . . . . . . . ",
+" . . . . . . . . > , ' ) ) ) ) ) ) ) ) ) ) ) ! ~ { ] . . . . . . . . ",
+" . . . . . . . . ^ / ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ( _ . . . . . . . . ",
+" . . . . . . . : < ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) [ } . . . . . . . ",
+" . . . . . . . | 1 ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) 2 | . . . . . . . ",
+" . . . . . . 3 4 ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) / 3 . . . . . . ",
+" . . . . . . : 5 ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) 6 7 . . . . . . ",
+" . . . . . . . [ ) ) ) ) ) ) ) ) ) ) ) ) 8 9 9 0 ) ) ) ) ) ) ) ) ) ) ) ) a . . . . . . . ",
+" . . . . . . b ) ) ) ) ) ) ) ) ! c d e f g . . . h i j ) ) ) ) ) ) ) ) ) ) k . . . . . . ",
+" . . . . . ] l ) ) ) ) ) ) ) ! d . . . . . . . . . . . m n ) ) ) ) ) ) ) ) ( ] . . . . . ",
+" . . . . . . { ) ) ) ) ) ) ) ) o . . . . . . . . . . . . . p 2 ) ) ) ) ) ) ) ) q . . . . . . ",
+" . . . . . . r ) ) ) ) ) ) ) ) s . . . . . . . . . . . . . . t ! ) ) ) ) ) ) ) u . . . . . . ",
+" . . . . . v ! ) ) ) ) ) ) ) ) w d x ; y y y z . . . . . . . . A ) ) ) ) ) ) ) ! B . . . . . ",
+". . . . . . C ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) D . . . . . . . E ) ) ) ) ) ) ) ) F . . . . . . ",
+". . . . . . G ) ) ) ) ) ) ) ) ) ) ) ) ) ) H I J K . . . . . . . L ) ) ) ) ) ) ) ) c . . . . . . ",
+". . . . . . $ ) ) ) ) ) ) ) ) ) ) ) 6 M N : . . . . . . . . . . O ) ) ) ) ) ) ) ) * . . . . . . ",
+". . . . . . 0 ) ) ) ) ) ) ) ) ) ! P > . . . . . . . . . . . . . : ) ) ) ) ) ) ) ) Q . . . . . . ",
+". . . . . . R ) ) ) ) ) ) ) ) ) - . . . . . . . . . . . . . . . : ) ) ) ) ) ) ) ) R . . . . . . ",
+". . . . . . R ) ) ) ) ) ) ) ) < . . . . . . . . . . . . . . . . S ) ) ) ) ) ) ) ) R . . . . . . ",
+". . . . . . 0 ) ) ) ) ) ) ) T p . . . . . . D 2 U m . . . . . . F ) ) ) ) ) ) ) ) Q . . . . . . ",
+". . . . . . V ) ) ) ) ) ) ) W . . . . . . . G ) ) X . . . . . . Y ) ) ) ) ) ) ) ) * . . . . . . ",
+". . . . . . # ) ) ) ) ) ) ) W . . . . . . . k 5 Z ` . . . . . . .) ) ) ) ) ) ) ) G . . . . . . ",
+". . . . . . M ) ) ) ) ) ) ) w x . . . . . . . . . . . . . . . . ..) ) ) ) ) ) ) ) C . . . . . . ",
+" . . . . . +.) ) ) ) ) ) ) ) @.. . . . . . . . . . . . . . . . q ) ) ) ) ) ) ) ) #.. . . . . ",
+" . . . . . . A ) ) ) ) ) ) ) V $.. . . . . . . . . . . . . . . %.) ) ) ) ) ) ) ' . . . . . . ",
+" . . . . . . , ) ) ) ) ) ) ) ) &.p . . . . . . > *.K . . . . =.-.) ) ) ) ) ) ) , . . . . . . ",
+" . . . . . > ;.) ) ) ) ) ) ) ) -.^ ] . . m >.% ) w ,.'.).{ !.) ) ) ) ) ) ) l > . . . . . ",
+" . . . . . . ~.) ) ) ) ) ) ) ) ) ) {. .~ ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) _ . . . . . . ",
+" . . . . . . . ].) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) a . . . . . . . ",
+" . . . . . . : 6 ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) 6 7 . . . . . . ",
+" . . . . . . 3 / ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) / 3 . . . . . . ",
+" . . . . . . . | 1 ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) U 3 . . . . . . . ",
+" . . . . . . . } [ ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ^.} . . . . . . . ",
+" . . . . . . . . b ;.) ) ) ) ) ) ) ) ) ) ) ) ) ) ) ) n k . . . . . . . . ",
+" . . . . . . . . > , ' ) ) ) ) ) ) ) ) ) ) ) ! ~ { ] . . . . . . . . ",
+" . . . . . . . . . . v C = /.Q R R Q 1 c F B . . . . . . . . . . ",
+" . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+" . . . . . . . . . . . . . . . . . . . . . . . . . . . . ",
+" . . . . . . . . . . . . . . . . . . . . . . . . ",
+" . . . . . . . . . . . . . . . . . . . . . . ",
+" . . . . . . . . . . . . . . . . ",
+" . . . . . . . . . . "};
diff --git a/src/audacious/input.c b/src/audacious/input.c
index ae3bf75..c5a6025 100644
--- a/src/audacious/input.c
+++ b/src/audacious/input.c
@@ -31,8 +31,8 @@
#include <mowgli.h>
#include "input.h"
+#include "output.h"
#include "plugin-registry.h"
-#include "probe.h"
PlaybackData ip_data =
{
@@ -73,133 +73,6 @@ GList * get_input_list (void)
return list;
}
-Tuple *
-input_get_song_tuple(const gchar * filename)
-{
- InputPlugin *ip = NULL;
- Tuple *input = NULL;
- gchar *ext = NULL;
-
- if (filename == NULL)
- return NULL;
-
- ip = file_probe (filename, FALSE);
-
- if (ip && ip->get_song_tuple)
- input = ip->get_song_tuple (filename);
- else
- {
- gchar *scratch;
-
- scratch = uri_to_display_basename(filename);
- tuple_associate_string(input, FIELD_FILE_NAME, NULL, scratch);
- g_free(scratch);
-
- scratch = uri_to_display_dirname(filename);
- tuple_associate_string(input, FIELD_FILE_PATH, NULL, scratch);
- g_free(scratch);
-
- ext = strrchr(filename, '.');
- if (ext != NULL) {
- ++ext;
- tuple_associate_string(input, FIELD_FILE_EXT, NULL, ext);
- }
-
- tuple_associate_int(input, FIELD_LENGTH, NULL, -1);
- }
-
- return input;
-}
-
-static void
-input_general_file_info_box(const gchar * filename, InputPlugin * ip)
-{
- GtkWidget *window, *vbox;
- GtkWidget *label, *filename_hbox, *filename_entry;
- GtkWidget *bbox, *cancel;
-
- gchar *title, *fileinfo, *basename, *iplugin;
- gchar *filename_utf8;
- gchar *realfn = NULL;
-
- window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
- gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
-
- realfn = g_filename_from_uri(filename, NULL, NULL);
- basename = g_path_get_basename(realfn ? realfn : filename);
- fileinfo = filename_to_utf8(basename);
- title = g_strdup_printf(_("audacious: %s"), fileinfo);
-
- gtk_window_set_title(GTK_WINDOW(window), title);
-
- g_free(title);
- g_free(fileinfo);
- g_free(basename);
-
- gtk_container_set_border_width(GTK_CONTAINER(window), 10);
-
- vbox = gtk_vbox_new(FALSE, 10);
- gtk_container_add(GTK_CONTAINER(window), vbox);
-
- filename_hbox = gtk_hbox_new(FALSE, 5);
- gtk_box_pack_start(GTK_BOX(vbox), filename_hbox, FALSE, TRUE, 0);
-
- label = gtk_label_new(_("Filename:"));
- gtk_box_pack_start(GTK_BOX(filename_hbox), label, FALSE, TRUE, 0);
-
- filename_entry = gtk_entry_new();
- filename_utf8 = filename_to_utf8(realfn ? realfn : filename);
- g_free(realfn); realfn = NULL;
-
- gtk_entry_set_text(GTK_ENTRY(filename_entry), filename_utf8);
- gtk_editable_set_editable(GTK_EDITABLE(filename_entry), FALSE);
- gtk_box_pack_start(GTK_BOX(filename_hbox), filename_entry, TRUE, TRUE, 0);
-
- g_free(filename_utf8);
-
- if (ip)
- if (ip->description)
- iplugin = ip->description;
- else
- iplugin = ip->filename;
- else
- iplugin = _("No input plugin recognized this file");
-
- title = g_strdup_printf(_("Input plugin: %s"), iplugin);
-
- label = gtk_label_new(title);
- gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
- gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_LEFT);
- g_free(title);
- gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, TRUE, 0);
-
- bbox = gtk_hbutton_box_new();
- gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
- gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
-
- cancel = gtk_button_new_from_stock(GTK_STOCK_CLOSE);
- g_signal_connect_swapped(G_OBJECT(cancel), "clicked",
- G_CALLBACK(gtk_widget_destroy),
- window);
- GTK_WIDGET_SET_FLAGS(cancel, GTK_CAN_DEFAULT);
- gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0);
-
- gtk_widget_show_all(window);
-}
-
-void input_file_info_box (const gchar * filename)
-{
- InputPlugin * decoder;
-
- decoder = file_probe (filename, FALSE);
-
- if (decoder != NULL && decoder->file_info_box != NULL)
- decoder->file_info_box (filename);
- else
- input_general_file_info_box (filename, decoder);
-}
-
void
input_get_volume(gint * l, gint * r)
{
diff --git a/src/audacious/input.h b/src/audacious/input.h
index b5afb90..2ca35f5 100644
--- a/src/audacious/input.h
+++ b/src/audacious/input.h
@@ -52,11 +52,8 @@ InputPlayback *get_current_input_playback(void);
void set_current_input_playback(InputPlayback * ip);
void set_current_input_data(void * data);
-Tuple *input_get_song_tuple(const gchar * filename);
-
void input_get_volume(gint * l, gint * r);
void input_set_volume(gint l, gint r);
-void input_file_info_box(const gchar * filename);
extern PlaybackData ip_data;
diff --git a/src/audacious/interface.c b/src/audacious/interface.c
index 8400fef..483f84d 100644
--- a/src/audacious/interface.c
+++ b/src/audacious/interface.c
@@ -21,6 +21,7 @@
#include <glib.h>
#include <glib/gi18n.h>
+#include <gtk/gtk.h>
#include "interface.h"
#include "playback.h"
@@ -181,8 +182,8 @@ interface_show_about_window(gboolean show)
}
}
-void
-interface_run_gtk_plugin(GtkWidget *parent, const gchar *name)
+/* void interface_run_gtk_plugin (GtkWidget * parent, const gchar * name) */
+void interface_run_gtk_plugin (void * parent, const gchar * name)
{
if (interface_cbs.run_gtk_plugin != NULL)
interface_cbs.run_gtk_plugin(parent, name);
@@ -201,8 +202,8 @@ interface_run_gtk_plugin(GtkWidget *parent, const gchar *name)
}
}
-void
-interface_stop_gtk_plugin(GtkWidget *parent)
+/* void interface_stop_gtk_plugin (GtkWidget * parent) */
+void interface_stop_gtk_plugin (void * parent)
{
if (interface_cbs.stop_gtk_plugin != NULL)
interface_cbs.stop_gtk_plugin(parent);
diff --git a/src/audacious/interface.h b/src/audacious/interface.h
index 41e76b8..7430707 100644
--- a/src/audacious/interface.h
+++ b/src/audacious/interface.h
@@ -29,15 +29,18 @@
#ifndef __AUDACIOUS2_INTERFACE_H__
#define __AUDACIOUS2_INTERFACE_H__
-#include <gtk/gtk.h>
#include <mowgli.h>
typedef struct {
- GtkWidget** (*create_prefs_window)(void);
+ /* GtkWidget * * (* create_prefs_window) (void); */
+ void * * (* create_prefs_window) (void);
void (*show_prefs_window)(void);
void (*hide_prefs_window)(void);
void (*destroy_prefs_window)(void);
- gint (*prefswin_page_new)(GtkWidget *container, gchar *name, gchar *imgurl);
+ /* gint (* prefswin_page_new) (GtkWidget * container, const gchar * name,
+ const gchar * imgurl); */
+ gint (* prefswin_page_new) (void * container, const gchar * name,
+ const gchar * imgurl);
} InterfaceOps;
typedef struct {
@@ -52,8 +55,10 @@ typedef struct {
void (*hide_about_window)(void);
void (*toggle_shuffle)(void);
void (*toggle_repeat)(void);
- GtkWidget *(*run_gtk_plugin)(GtkWidget *parent, const gchar *name);
- GtkWidget *(*stop_gtk_plugin)(GtkWidget *parent);
+ /* GtkWidget * (* run_gtk_plugin) (GtkWidget * parent, const gchar * name); */
+ void * (* run_gtk_plugin) (void * parent, const gchar * name);
+ /* GtkWidget * (* stop_gtk_plugin) (GtkWidget * parent); */
+ void * (* stop_gtk_plugin) (void * parent);
} InterfaceCbs;
typedef struct _Interface {
@@ -82,8 +87,10 @@ void interface_hide_filebrowser(void);
void interface_toggle_visibility(void);
void interface_show_error_message(const gchar * markup);
void interface_show_jump_to_track(void);
-void interface_run_gtk_plugin(GtkWidget *parent, const gchar *name);
-void interface_stop_gtk_plugin(GtkWidget *parent);
+/* void interface_run_gtk_plugin (GtkWidget * parent, const gchar * name); */
+void interface_run_gtk_plugin (void * parent, const gchar * name);
+/* void interface_stop_gtk_plugin (GtkWidget * parent); */
+void interface_stop_gtk_plugin (void * parent);
void interface_toggle_shuffle(void);
void interface_toggle_repeat(void);
diff --git a/src/audacious/main.c b/src/audacious/main.c
index 4c2dc3c..8280303 100644
--- a/src/audacious/main.c
+++ b/src/audacious/main.c
@@ -43,7 +43,6 @@
#include "eggdesktopfile.h"
#endif
-#include "build_stamp.h"
#include "configdb.h"
#include "equalizer.h"
#include "hook.h"
@@ -58,10 +57,13 @@
#include "util.h"
#include "vfs.h"
#include "chardet.h"
+#include "audtag.h"
#include "ui_headless.h"
#include "ui_misc.h"
+#define AUTOSAVE_INTERVAL 300 /* seconds */
+
static const gchar *application_name = N_("Audacious");
struct _AudCmdLineOpt
@@ -89,7 +91,7 @@ MprisPlayer *mpris;
static void print_version(void)
{
- g_printf("%s %s [%s]\n", _(application_name), VERSION, build_stamp);
+ g_printf("%s %s (%s)\n", _(application_name), VERSION, BUILDSTAMP);
}
static void aud_make_user_dir(void)
@@ -133,11 +135,7 @@ static void aud_init_paths()
aud_paths[BMP_PATH_PLAYLISTS_DIR] = g_build_filename(aud_paths[BMP_PATH_USER_DIR], "playlists", NULL);
aud_paths[BMP_PATH_CONFIG_FILE] = g_build_filename(aud_paths[BMP_PATH_USER_DIR], "config", NULL);
-#ifdef HAVE_XSPF_PLAYLIST
aud_paths[BMP_PATH_PLAYLIST_FILE] = g_build_filename(aud_paths[BMP_PATH_USER_DIR], "playlist.xspf", NULL);
-#else
- aud_paths[BMP_PATH_PLAYLIST_FILE] = g_build_filename(aud_paths[BMP_PATH_USER_DIR], "playlist.m3u", NULL);
-#endif
aud_paths[BMP_PATH_ACCEL_FILE] = g_build_filename(aud_paths[BMP_PATH_USER_DIR], "accels", NULL);
aud_paths[BMP_PATH_LOG_FILE] = g_build_filename(aud_paths[BMP_PATH_USER_DIR], "log", NULL);
@@ -200,7 +198,7 @@ static void parse_cmd_line_options(gint * argc, gchar *** argv)
exit(EXIT_FAILURE);
}
- g_free(context);
+ g_option_context_free (context);
}
static void handle_cmd_line_filenames(gboolean is_running)
@@ -352,46 +350,13 @@ static void aud_setup_logger(void)
g_atexit(aud_logger_stop);
}
-static gboolean load_extra_playlist(const gchar * path, const gchar * basename, gpointer def)
-{
- gchar * filename = g_filename_to_uri (path, NULL, NULL);
- gint playlist = playlist_count();
-
- playlist_insert(playlist);
- playlist_insert_playlist(playlist, 0, filename);
-
- g_free (filename);
-
- return FALSE; /* keep loading other playlists */
-}
-
-static void playlist_system_init()
-{
- gchar * filename = g_filename_to_uri (aud_paths[BMP_PATH_PLAYLIST_FILE],
- NULL, NULL);
-
- playlist_init();
-
- if (vfs_file_test (filename, G_FILE_TEST_EXISTS))
- playlist_insert_playlist (0, 0, filename);
-
- g_free (filename);
-
- /* Load extra playlists */
- if (!dir_foreach(aud_paths[BMP_PATH_PLAYLISTS_DIR], load_extra_playlist, NULL, NULL))
- g_warning("Could not load extra playlists\n");
-
- playlist_load_state ();
- playlist_set_shuffle(cfg.shuffle);
-}
-
void aud_quit(void)
{
Interface *i = interface_get(options.interface);
g_message("Saving configuration");
aud_config_save();
- playlist_save_state ();
+ save_playlists ();
if (playback_get_playing ())
playback_stop ();
@@ -447,6 +412,14 @@ void init_playback_hooks(void)
}
#endif
+static gboolean autosave_cb (void * unused)
+{
+ g_message ("Saving configuration.\n");
+ aud_config_save ();
+ save_playlists ();
+ return TRUE;
+}
+
gint main(gint argc, gchar ** argv)
{
Interface *i;
@@ -463,6 +436,7 @@ gint main(gint argc, gchar ** argv)
gdk_threads_init();
mowgli_init();
chardet_init();
+ tag_init();
hook_init();
hook_associate("quit", quit_cb, 0);
@@ -500,6 +474,7 @@ gint main(gint argc, gchar ** argv)
g_message("Loading configuration");
aud_config_load();
+ atexit (aud_config_free);
g_message("Initializing signal handlers");
signal_handlers_init();
@@ -531,8 +506,9 @@ gint main(gint argc, gchar ** argv)
exit(EXIT_SUCCESS);
}
- playlist_system_init();
- init_equalizer ();
+ playlist_init ();
+ load_playlists ();
+ eq_init ();
g_message("Handling commandline options, part #2");
handle_cmd_line_options();
@@ -545,6 +521,8 @@ gint main(gint argc, gchar ** argv)
ui_display_unsupported_version_warning();
#endif
+ g_timeout_add_seconds (AUTOSAVE_INTERVAL, autosave_cb, NULL);
+
g_message("Selecting interface %s", options.interface);
i = interface_get(options.interface);
diff --git a/src/audacious/output.c b/src/audacious/output.c
index 802eb32..f00dd20 100644
--- a/src/audacious/output.c
+++ b/src/audacious/output.c
@@ -26,7 +26,7 @@
#include "audio.h"
#include "audconfig.h"
#include "effect.h"
-#include "equalizer_flow.h"
+#include "equalizer.h"
#include "flow.h"
#include "output.h"
#include "playback.h"
@@ -111,7 +111,6 @@ static void drain (void);
/* output_mutex must be locked */
static void real_close (void)
{
- new_effect_flush ();
vis_runner_start_stop (FALSE, FALSE);
COP->close_audio ();
output_opened = FALSE;
@@ -148,36 +147,34 @@ static gboolean output_open_audio (AFormat format, gint rate, gint channels)
LOCK;
- if (output_leave_open)
+ if (output_leave_open && COP->set_written_time != NULL)
{
- if (channels == decoder_channels && rate == decoder_rate &&
- COP->set_written_time != NULL)
- {
- vis_runner_time_offset (- frames_written * 1000 / decoder_rate);
- COP->set_written_time (0);
- output_opened = TRUE;
- }
- else
- {
- UNLOCK;
- drain ();
- LOCK;
- real_close ();
- }
+ vis_runner_time_offset (- frames_written * (gint64) 1000 / decoder_rate);
+ COP->set_written_time (0);
}
decoder_format = format;
decoder_channels = channels;
decoder_rate = rate;
frames_written = 0;
- output_leave_open = FALSE;
- output_paused = FALSE;
- if (! output_opened)
+ effect_channels = channels;
+ effect_rate = rate;
+ new_effect_start (& effect_channels, & effect_rate);
+ eq_set_format (effect_channels, effect_rate);
+
+ if (output_leave_open && COP->set_written_time != NULL && effect_channels ==
+ output_channels && effect_rate == output_rate)
+ output_opened = TRUE;
+ else
{
- effect_channels = channels;
- effect_rate = rate;
- new_effect_start (& effect_channels, & effect_rate);
+ if (output_leave_open)
+ {
+ UNLOCK;
+ drain ();
+ LOCK;
+ real_close ();
+ }
output_format = cfg.output_bit_depth == 32 ? FMT_S32_NE :
cfg.output_bit_depth == 24 ? FMT_S24_NE : cfg.output_bit_depth == 16 ?
@@ -192,6 +189,9 @@ static gboolean output_open_audio (AFormat format, gint rate, gint channels)
}
}
+ output_leave_open = FALSE;
+ output_paused = FALSE;
+
UNLOCK;
return output_opened;
}
@@ -200,8 +200,13 @@ static void output_close_audio (void)
{
LOCK;
+ output_opened = FALSE;
+
if (! output_leave_open)
+ {
+ new_effect_flush ();
real_close ();
+ }
UNLOCK;
}
@@ -232,7 +237,7 @@ static gint get_written_time (void)
LOCK;
if (output_opened)
- time = frames_written * 1000 / decoder_rate;
+ time = frames_written * (gint64) 1000 / decoder_rate;
UNLOCK;
return time;
@@ -254,19 +259,6 @@ static gboolean output_buffer_playing (void)
return FALSE;
}
-static Flow * get_postproc_flow (void)
-{
- static Flow * flow = NULL;
-
- if (flow == NULL)
- {
- flow = flow_new ();
- flow_link_element (flow, equalizer_flow);
- }
-
- return flow;
-}
-
static Flow * get_legacy_flow (void)
{
static Flow * flow = NULL;
@@ -358,15 +350,7 @@ static void do_write (void * data, gint samples)
{
void * allocated = NULL;
- samples = flow_execute (get_postproc_flow (), 0, & data, sizeof (gfloat) *
- samples, FMT_FLOAT, effect_rate, effect_channels) / sizeof (gfloat);
-
- if (data != allocated)
- {
- g_free (allocated);
- allocated = NULL;
- }
-
+ eq_filter (data, samples);
apply_software_volume (data, output_channels, samples / output_channels);
if (output_format != FMT_FLOAT)
@@ -436,8 +420,8 @@ static void output_write_audio (void * data, gint size)
}
apply_replay_gain (data, samples);
- vis_runner_pass_audio (frames_written * 1000 / decoder_rate, data, samples,
- decoder_channels);
+ vis_runner_pass_audio (frames_written * (gint64) 1000 / decoder_rate, data,
+ samples, decoder_channels);
new_effect_process ((gfloat * *) & data, & samples);
if (data != allocated)
@@ -461,8 +445,6 @@ static void write_buffers (void)
static void drain (void)
{
- write_buffers ();
-
if (COP->buffer_playing != NULL)
{
while (COP->buffer_playing ())
@@ -508,6 +490,7 @@ void output_drain (void)
if (output_leave_open)
{
UNLOCK;
+ write_buffers (); /* tell effect plugins this is the last song */
drain ();
LOCK;
real_close ();
@@ -530,13 +513,6 @@ void set_current_output_plugin (OutputPlugin * plugin)
playback_stop ();
}
- LOCK;
-
- if (output_leave_open)
- real_close ();
-
- UNLOCK;
-
/* This function is also used to restart playback (for example, when
resampling is switched on or off), in which case we don't need to do an
init cycle. -jlindgren */
diff --git a/src/audacious/playback.c b/src/audacious/playback.c
index b1942a0..e19a38a 100644
--- a/src/audacious/playback.c
+++ b/src/audacious/playback.c
@@ -50,8 +50,9 @@
static void set_params (InputPlayback * playback, const gchar * title, gint
length, gint bitrate, gint samplerate, gint channels);
-static void set_title (InputPlayback * playback, const gchar * title);
static void set_tuple (InputPlayback * playback, Tuple * tuple);
+static void set_gain_from_playlist (InputPlayback * playback);
+
static gboolean playback_segmented_end(gpointer data);
static gboolean playback_play_file (gint playlist, gint entry);
@@ -60,6 +61,54 @@ static gboolean pause_when_ready;
static gint seek_when_ready;
static gint ready_source;
static gint failed_entries;
+static gint set_tuple_source = 0;
+static Tuple * tuple_to_be_set = NULL;
+static ReplayGainInfo gain_from_playlist;
+
+static void cancel_set_tuple (void)
+{
+ if (set_tuple_source != 0)
+ {
+ g_source_remove (set_tuple_source);
+ set_tuple_source = 0;
+ }
+
+ if (tuple_to_be_set != NULL)
+ {
+ tuple_free (tuple_to_be_set);
+ tuple_to_be_set = NULL;
+ }
+}
+
+/* clears gain info if tuple == NULL */
+static void read_gain_from_tuple (Tuple * tuple)
+{
+ gint album_gain, album_peak, track_gain, track_peak, gain_unit, peak_unit;
+
+ memset (& gain_from_playlist, 0, sizeof gain_from_playlist);
+
+ if (tuple == NULL)
+ return;
+
+ album_gain = tuple_get_int (tuple, FIELD_GAIN_ALBUM_GAIN, NULL);
+ album_peak = tuple_get_int (tuple, FIELD_GAIN_ALBUM_PEAK, NULL);
+ track_gain = tuple_get_int (tuple, FIELD_GAIN_TRACK_GAIN, NULL);
+ track_peak = tuple_get_int (tuple, FIELD_GAIN_TRACK_PEAK, NULL);
+ gain_unit = tuple_get_int (tuple, FIELD_GAIN_GAIN_UNIT, NULL);
+ peak_unit = tuple_get_int (tuple, FIELD_GAIN_PEAK_UNIT, NULL);
+
+ if (gain_unit)
+ {
+ gain_from_playlist.album_gain = album_gain / (gfloat) gain_unit;
+ gain_from_playlist.track_gain = track_gain / (gfloat) gain_unit;
+ }
+
+ if (peak_unit)
+ {
+ gain_from_playlist.album_peak = album_peak / (gfloat) peak_unit;
+ gain_from_playlist.track_peak = track_peak / (gfloat) peak_unit;
+ }
+}
static gboolean ready_cb (void * data)
{
@@ -162,19 +211,20 @@ playback_get_time_real(void)
return time;
}
-gint
-playback_get_time(void)
+gint playback_get_time (void)
{
InputPlayback * playback;
playback = ip_data.current_input_playback;
g_return_val_if_fail (playback != NULL, 0);
- return playback_get_time_real() - playback->start;
+ if (playback->start > 0)
+ return playback_get_time_real () - playback->start;
+ else
+ return playback_get_time_real ();
}
-void
-playback_initiate(void)
+void playback_initiate (void)
{
gint playlist, entry;
@@ -241,7 +291,8 @@ void playback_pause (void)
hook_call("playback unpause", NULL);
if (playback->end > 0)
- playback->end_timeout = g_timeout_add(playback_get_time_real() - playback->start, playback_segmented_end, playback);
+ playback->end_timeout = g_timeout_add (playback->end -
+ playback_get_time_real (), playback_segmented_end, playback);
}
}
@@ -271,6 +322,7 @@ static void playback_finalize (InputPlayback * playback)
playback_free (playback);
ip_data.current_input_playback = NULL;
+ cancel_set_tuple ();
if (playback->end_timeout)
g_source_remove(playback->end_timeout);
@@ -291,16 +343,6 @@ void playback_stop (void)
hook_call ("playback stop", NULL);
}
-static void
-run_no_output_plugin_dialog(void)
-{
- const gchar *markup =
- N_("<b><big>No output plugin selected.</big></b>\n"
- "You have not selected an output plugin.");
-
- interface_show_error_message(markup);
-}
-
static gboolean playback_ended (void * user_data)
{
gint playlist = playlist_get_playing ();
@@ -324,8 +366,7 @@ static gboolean playback_ended (void * user_data)
if (! (play = playlist_next_song (playlist, cfg.repeat)))
playlist_set_position (playlist, -1);
- if (failed_entries >= 100 || failed_entries >= playlist_entry_count
- (playlist) * 2)
+ if (failed_entries >= 10)
play = FALSE;
}
@@ -406,6 +447,10 @@ playback_monitor_thread(gpointer data)
static void playback_set_replaygain_info (InputPlayback * playback,
ReplayGainInfo * info)
{
+ fprintf (stderr, "Plugin %s should be updated to use OutputAPI::"
+ "set_replaygain_info or (better) InputPlayback::set_gain_from_playlist.\n",
+ playback->plugin->description);
+
playback->output->set_replaygain_info (info);
}
@@ -413,6 +458,15 @@ static void playback_set_replaygain_info (InputPlayback * playback,
static void playback_pass_audio (InputPlayback * playback, AFormat format, gint
channels, gint size, void * data, gint * going)
{
+ static gboolean warned = FALSE;
+
+ if (! warned)
+ {
+ fprintf (stderr, "Plugin %s should be updated to use OutputAPI::"
+ "write_audio.\n", playback->plugin->description);
+ warned = TRUE;
+ }
+
playback->output->write_audio (data, size);
}
@@ -434,8 +488,8 @@ playback_new(void)
playback->set_pb_ready = playback_set_pb_ready;
playback->set_pb_change = playback_set_pb_change;
playback->set_params = set_params;
- playback->set_title = set_title;
playback->set_tuple = set_tuple;
+ playback->set_gain_from_playlist = set_gain_from_playlist;
/* compatibility */
playback->set_replaygain_info = playback_set_replaygain_info;
@@ -484,23 +538,31 @@ static gboolean playback_play_file (gint playlist, gint entry)
const gchar * filename = playlist_entry_get_filename (playlist, entry);
const gchar * title = playlist_entry_get_title (playlist, entry);
InputPlugin * decoder = playlist_entry_get_decoder (playlist, entry);
+ Tuple * tuple = (Tuple *) playlist_entry_get_tuple (playlist, entry);
InputPlayback *playback;
- if (current_output_plugin == NULL)
- {
- run_no_output_plugin_dialog ();
- return FALSE;
- }
-
if (decoder == NULL)
- decoder = file_probe (filename, FALSE);
+ decoder = file_find_decoder (filename, FALSE);
if (decoder == NULL)
{
- g_warning("Cannot play %s: no decoder found.\n", filename);
+ gchar * error = g_strdup_printf (_("No decoder found for %s."), filename);
+
+ interface_show_error_message (error);
+ g_free (error);
return FALSE;
}
+ if (tuple == NULL)
+ {
+ tuple = file_read_tuple (filename, decoder);
+
+ if (tuple != NULL)
+ playlist_entry_set_tuple (playlist, entry, tuple);
+ }
+
+ read_gain_from_tuple (tuple); /* even if tuple == NULL */
+
ip_data.playing = TRUE;
ip_data.paused = FALSE;
ip_data.stop = FALSE;
@@ -524,7 +586,7 @@ static gboolean playback_play_file (gint playlist, gint entry)
#endif
hook_associate ("playlist update", update_cb, NULL);
- hook_call ("playback begin", NULL);
+ hook_call ("playback begin", playback);
return TRUE;
}
@@ -585,13 +647,6 @@ void playback_seek (gint time)
static void set_params (InputPlayback * playback, const gchar * title, gint
length, gint bitrate, gint samplerate, gint channels)
{
- g_return_if_fail (playback != NULL);
-
- /* deprecated usage */
- if (title != NULL || length != 0)
- g_warning ("%s needs to be updated to use InputPlayback::set_tuple\n",
- playback->plugin->description);
-
playback->rate = bitrate;
playback->freq = samplerate;
playback->nch = channels;
@@ -599,25 +654,30 @@ static void set_params (InputPlayback * playback, const gchar * title, gint
event_queue ("info change", NULL);
}
-/* deprecated */
-static void set_title (InputPlayback * playback, const gchar * title)
-{
- g_warning ("%s needs to be updated to use InputPlayback::set_tuple\n",
- playback->plugin->description);
-}
-
-static gboolean set_tuple_cb (void * tuple)
+static gboolean set_tuple_cb (void * unused)
{
gint playlist = playlist_get_playing ();
- playlist_entry_set_tuple (playlist, playlist_get_position (playlist), tuple);
+ playlist_entry_set_tuple (playlist, playlist_get_position (playlist),
+ tuple_to_be_set);
+ set_tuple_source = 0;
+ tuple_to_be_set = NULL;
return FALSE;
}
static void set_tuple (InputPlayback * playback, Tuple * tuple)
{
/* playlist_entry_set_tuple must execute in main thread */
- g_timeout_add (0, set_tuple_cb, tuple);
+ cancel_set_tuple ();
+ set_tuple_source = g_timeout_add (0, set_tuple_cb, NULL);
+ tuple_to_be_set = tuple;
+
+ read_gain_from_tuple (tuple);
+}
+
+static void set_gain_from_playlist (InputPlayback * playback)
+{
+ playback->output->set_replaygain_info (& gain_from_playlist);
}
gchar * playback_get_title (void)
diff --git a/src/audacious/playlist-new.c b/src/audacious/playlist-new.c
index 183cca8..635039f 100644
--- a/src/audacious/playlist-new.c
+++ b/src/audacious/playlist-new.c
@@ -107,7 +107,7 @@ struct entry
gint length;
gboolean failed;
gboolean selected;
- gboolean shuffle_num;
+ gint shuffle_num;
gboolean queued;
gboolean segmented;
gint start;
@@ -122,7 +122,7 @@ struct playlist
struct index *entries;
struct entry *position;
gint selected_count;
- gint shuffle_num, last_shuffle_num;
+ gint last_shuffle_num;
GList *queued;
gint64 total_length;
gint64 selected_length;
@@ -142,9 +142,6 @@ static Tuple * scan_tuple;
static GThread * scan_thread;
static gint scan_position, updated_ago;
-static gint(*current_filename_compare) (const gchar * a, const gchar * b);
-static gint(*current_tuple_compare) (const Tuple * a, const Tuple * b);
-
static void * scanner (void * unused);
static gchar *title_from_tuple(Tuple * tuple)
@@ -267,7 +264,7 @@ static void entry_check_has_decoder (struct entry * entry)
if (entry->decoder != NULL || entry->failed)
return;
- entry->decoder = file_probe (entry->filename, TRUE);
+ entry->decoder = file_find_decoder (entry->filename, TRUE);
if (entry->decoder == NULL)
entry->failed = TRUE;
@@ -283,7 +280,6 @@ static struct playlist *playlist_new(void)
playlist->entries = index_new();
playlist->position = NULL;
playlist->selected_count = 0;
- playlist->shuffle_num = 0;
playlist->last_shuffle_num = 0;
playlist->queued = NULL;
playlist->total_length = 0;
@@ -365,27 +361,6 @@ static void queue_update (gint level)
NULL);
}
-static Tuple * get_tuple (const gchar * filename, InputPlugin * decoder)
-{
- if (decoder->get_song_tuple != NULL)
- return decoder->get_song_tuple (filename);
-
- if (decoder->probe_for_tuple != NULL)
- {
- VFSFile * handle = vfs_fopen (filename, "r");
- Tuple * tuple;
-
- if (handle == NULL)
- return NULL;
-
- tuple = decoder->probe_for_tuple (filename, handle);
- vfs_fclose (handle);
- return tuple;
- }
-
- return NULL;
-}
-
/* scan_mutex must be locked! */
void scan_receive (void)
{
@@ -484,7 +459,7 @@ static void * scanner (void * unused)
if (scan_filename == NULL)
return NULL;
- scan_tuple = get_tuple (scan_filename, scan_decoder);
+ scan_tuple = file_read_tuple (scan_filename, scan_decoder);
scan_continue ();
}
}
@@ -500,7 +475,7 @@ static void check_scanned (struct playlist * playlist, struct entry * entry)
if (entry->tuple == NULL && ! entry->failed) /* scanner did it for us? */
{
- entry_set_tuple (playlist, entry, get_tuple (entry->filename,
+ entry_set_tuple (playlist, entry, file_read_tuple (entry->filename,
entry->decoder));
if (entry->tuple == NULL)
@@ -580,6 +555,41 @@ void playlist_insert(gint at)
hook_call ("playlist insert", GINT_TO_POINTER (at));
}
+void playlist_reorder (gint from, gint to, gint count)
+{
+ struct index * displaced;
+
+ g_return_if_fail (from >= 0 && from + count <= index_count (playlists));
+ g_return_if_fail (to >= 0 && to + count <= index_count (playlists));
+ g_return_if_fail (count >= 0);
+
+ PLAYLIST_WILL_CHANGE;
+
+ displaced = index_new ();
+
+ if (to < from)
+ index_copy_append (playlists, to, displaced, from - to);
+ else
+ index_copy_append (playlists, from + count, displaced, to - from);
+
+ index_move (playlists, from, to, count);
+
+ if (to < from)
+ {
+ index_copy_set (displaced, 0, playlists, to + count, from - to);
+ number_playlists (to, from + count - to);
+ }
+ else
+ {
+ index_copy_set (displaced, 0, playlists, from, to - from);
+ number_playlists (from, to + count - from);
+ }
+
+ index_free (displaced);
+
+ PLAYLIST_HAS_CHANGED;
+}
+
void playlist_delete (gint playlist_num)
{
DECLARE_PLAYLIST;
@@ -677,7 +687,10 @@ void playlist_set_playing(gint playlist_num)
{
DECLARE_PLAYLIST;
- LOOKUP_PLAYLIST;
+ if (playlist_num == -1)
+ playlist = NULL;
+ else
+ LOOKUP_PLAYLIST;
if (playing_playlist != NULL && playback_get_playing ())
playback_stop();
@@ -690,8 +703,13 @@ gint playlist_get_playing(void)
return (playing_playlist == NULL) ? -1 : playing_playlist->number;
}
+/* If we are already at the song or it is already at the top of the shuffle
+ * list, we let it be. Otherwise, we move it to the top. */
static void set_position (struct playlist * playlist, struct entry * entry)
{
+ if (entry == playlist->position)
+ return;
+
playlist->position = entry;
if (entry == NULL)
@@ -702,8 +720,6 @@ static void set_position (struct playlist * playlist, struct entry * entry)
playlist->last_shuffle_num ++;
entry->shuffle_num = playlist->last_shuffle_num;
}
-
- playlist->shuffle_num = entry->shuffle_num;
}
gint playlist_entry_count(gint playlist_num)
@@ -719,11 +735,11 @@ static void make_entries (gchar * filename, InputPlugin * decoder, Tuple *
tuple, struct index * list)
{
if (tuple == NULL && decoder == NULL)
- decoder = file_probe (filename, TRUE);
+ decoder = file_find_decoder (filename, TRUE);
- if (tuple == NULL && decoder != NULL && decoder->have_subtune &&
- decoder->get_song_tuple != NULL)
- tuple = decoder->get_song_tuple (filename);
+ if (tuple == NULL && decoder != NULL && decoder->have_subtune && strchr
+ (filename, '?') == NULL)
+ tuple = file_read_tuple (filename, decoder);
if (tuple != NULL && tuple->nsubtunes > 0)
{
@@ -1290,36 +1306,40 @@ void playlist_randomize(gint playlist_num)
PLAYLIST_HAS_CHANGED;
}
-static gint filename_compare(const void **a, const void **b)
+static gint filename_compare (const void * _a, const void * _b, void * _compare)
{
- const struct entry *entry_a = *a, *entry_b = *b;
+ const struct entry * a = _a, * b = _b;
+ gint (* compare) (const gchar * a, const gchar * b) = _compare;
- return current_filename_compare(entry_a->filename, entry_b->filename);
+ return compare (a->filename, b->filename);
}
-static gint tuple_compare(const void **a, const void **b)
+static gint tuple_compare (const void * _a, const void * _b, void * _compare)
{
- const struct entry *entry_a = *a, *entry_b = *b;
+ const struct entry * a = _a, * b = _b;
+ gint (* compare) (const Tuple * a, const Tuple * b) = _compare;
- if (entry_a->tuple == NULL)
- return (entry_b->tuple == NULL) ? 0 : -1;
- if (entry_b->tuple == NULL)
+ if (a->tuple == NULL)
+ return (b->tuple == NULL) ? 0 : -1;
+ if (b->tuple == NULL)
return 1;
- return current_tuple_compare(entry_a->tuple, entry_b->tuple);
+ return compare (a->tuple, b->tuple);
}
-static void sort(struct playlist *playlist, gint(*compare) (const void **a, const void **b))
+static void sort (struct playlist * playlist, gint (* compare) (const void * a,
+ const void * b, void * inner), void * inner)
{
PLAYLIST_WILL_CHANGE;
- index_sort(playlist->entries, compare);
- number_entries(playlist, 0, index_count(playlist->entries));
+ index_sort_with_data (playlist->entries, compare, inner);
+ number_entries (playlist, 0, index_count (playlist->entries));
PLAYLIST_HAS_CHANGED;
}
-static void sort_selected(struct playlist *playlist, gint(*compare) (const void **a, const void **b))
+static void sort_selected (struct playlist * playlist, gint (* compare)
+ (const void * a, const void * b, void * inner), void * inner)
{
gint entries, count, count2;
struct index *selected;
@@ -1337,7 +1357,7 @@ static void sort_selected(struct playlist *playlist, gint(*compare) (const void
index_append(selected, entry);
}
- index_sort(selected, compare);
+ index_sort_with_data (selected, compare, inner);
count2 = 0;
@@ -1355,17 +1375,18 @@ static void sort_selected(struct playlist *playlist, gint(*compare) (const void
PLAYLIST_HAS_CHANGED;
}
-void playlist_sort_by_filename(gint playlist_num, gint(*compare) (const gchar * a, const gchar * b))
+void playlist_sort_by_filename (gint playlist_num, gint (* compare)
+ (const gchar * a, const gchar * b))
{
DECLARE_PLAYLIST;
LOOKUP_PLAYLIST;
- current_filename_compare = compare;
- sort(playlist, filename_compare);
+ sort (playlist, filename_compare, compare);
}
-void playlist_sort_by_tuple(gint playlist_num, gint(*compare) (const Tuple * a, const Tuple * b))
+void playlist_sort_by_tuple (gint playlist_num, gint (* compare)
+ (const Tuple * a, const Tuple * b))
{
DECLARE_PLAYLIST;
gint entries, count;
@@ -1380,21 +1401,21 @@ void playlist_sort_by_tuple(gint playlist_num, gint(*compare) (const Tuple * a,
check_scanned (playlist, entry);
}
- current_tuple_compare = compare;
- sort(playlist, tuple_compare);
+ sort (playlist, tuple_compare, compare);
}
-void playlist_sort_selected_by_filename(gint playlist_num, gint(*compare) (const gchar * a, const gchar * b))
+void playlist_sort_selected_by_filename (gint playlist_num, gint (* compare)
+ (const gchar * a, const gchar * b))
{
DECLARE_PLAYLIST;
LOOKUP_PLAYLIST;
- current_filename_compare = compare;
- sort_selected(playlist, filename_compare);
+ sort_selected (playlist, filename_compare, compare);
}
-void playlist_sort_selected_by_tuple(gint playlist_num, gint(*compare) (const Tuple * a, const Tuple * b))
+void playlist_sort_selected_by_tuple (gint playlist_num, gint (* compare)
+ (const Tuple * a, const Tuple * b))
{
DECLARE_PLAYLIST;
gint entries, count;
@@ -1410,11 +1431,10 @@ void playlist_sort_selected_by_tuple(gint playlist_num, gint(*compare) (const Tu
check_scanned (playlist, entry);
}
- current_tuple_compare = compare;
- sort_selected(playlist, tuple_compare);
+ sort_selected (playlist, tuple_compare, compare);
}
-void playlist_reformat_titles()
+void playlist_reformat_titles (void)
{
gint playlist_num;
@@ -1459,6 +1479,34 @@ void playlist_rescan(gint playlist_num)
METADATA_HAS_CHANGED;
}
+void playlist_rescan_file (const gchar * filename)
+{
+ gint num_playlists = index_count (playlists);
+ gint playlist_num;
+
+ METADATA_WILL_CHANGE;
+
+ for (playlist_num = 0; playlist_num < num_playlists; playlist_num ++)
+ {
+ struct playlist * playlist = index_get (playlists, playlist_num);
+ gint num_entries = index_count (playlist->entries);
+ gint entry_num;
+
+ for (entry_num = 0; entry_num < num_entries; entry_num ++)
+ {
+ struct entry * entry = index_get (playlist->entries, entry_num);
+
+ if (! strcmp (entry->filename, filename))
+ {
+ entry_set_tuple (playlist, entry, NULL);
+ entry->failed = FALSE;
+ }
+ }
+ }
+
+ METADATA_HAS_CHANGED;
+}
+
gint64 playlist_get_total_length(gint playlist_num)
{
DECLARE_PLAYLIST;
@@ -1477,10 +1525,6 @@ gint64 playlist_get_selected_length(gint playlist_num)
return playlist->selected_length;
}
-void playlist_set_shuffle (gboolean on) /* currently not needed */
-{
-}
-
gint playlist_queue_count(gint playlist_num)
{
DECLARE_PLAYLIST;
@@ -1610,8 +1654,9 @@ static gboolean shuffle_prev (struct playlist * playlist)
{
struct entry * entry = index_get (playlist->entries, count);
- if (entry->shuffle_num && entry->shuffle_num < playlist->shuffle_num &&
- (found == NULL || entry->shuffle_num > found->shuffle_num))
+ if (entry->shuffle_num && (playlist->position == NULL ||
+ entry->shuffle_num < playlist->position->shuffle_num) && (found == NULL
+ || entry->shuffle_num > found->shuffle_num))
found = entry;
}
@@ -1619,7 +1664,6 @@ static gboolean shuffle_prev (struct playlist * playlist)
return FALSE;
playlist->position = found;
- playlist->shuffle_num = found->shuffle_num;
return TRUE;
}
@@ -1629,14 +1673,7 @@ gboolean playlist_prev_song(gint playlist_num)
LOOKUP_PLAYLIST_RET (FALSE);
- if (playlist->queued != NULL)
- {
- if (playlist->position == playlist->queued->data)
- return FALSE;
-
- set_position (playlist, playlist->queued->data);
- }
- else if (cfg.shuffle)
+ if (cfg.shuffle)
{
if (! shuffle_prev (playlist))
return FALSE;
@@ -1670,15 +1707,15 @@ static gboolean shuffle_next (struct playlist * playlist)
if (! entry->shuffle_num)
choice ++;
- else if (entry->shuffle_num > playlist->shuffle_num && (found == NULL ||
- entry->shuffle_num < found->shuffle_num))
+ else if (playlist->position != NULL && entry->shuffle_num >
+ playlist->position->shuffle_num && (found == NULL || entry->shuffle_num
+ < found->shuffle_num))
found = entry;
}
if (found != NULL)
{
playlist->position = found;
- playlist->shuffle_num = found->shuffle_num;
return TRUE;
}
@@ -1708,7 +1745,6 @@ static void shuffle_reset (struct playlist * playlist)
{
gint entries = index_count (playlist->entries), count;
- playlist->shuffle_num = 0;
playlist->last_shuffle_num = 0;
for (count = 0; count < entries; count ++)
@@ -1805,7 +1841,6 @@ void playlist_save_state (void)
fprintf (handle, "playlist %d\n", playlist_num);
fprintf (handle, "position %d\n", playlist_get_position (playlist_num));
- fprintf (handle, "shuffled %d\n", playlist->shuffle_num);
fprintf (handle, "last-shuffled %d\n", playlist->last_shuffle_num);
for (count = 0; count < entries; count ++)
@@ -1855,7 +1890,7 @@ void playlist_load_state (void)
{
gchar scratch[512];
FILE * handle;
- gint playlist_num;
+ gint playlist_num, obsolete = 0;
snprintf (scratch, sizeof scratch, "%s/" STATE_FILE,
aud_paths[BMP_PATH_USER_DIR]);
@@ -1892,13 +1927,13 @@ void playlist_load_state (void)
if (position >= 0 && position < entries)
playlist->position = index_get (playlist->entries, position);
- if (parse_integer ("shuffled", & playlist->shuffle_num))
+ if (parse_integer ("shuffled", & obsolete)) /* compatibility with 2.3 */
parse_next (handle);
if (parse_integer ("last-shuffled", & playlist->last_shuffle_num))
parse_next (handle);
else /* compatibility with 2.3 beta */
- playlist->last_shuffle_num = playlist->shuffle_num;
+ playlist->last_shuffle_num = obsolete;
for (count = 0; count < entries; count ++)
{
diff --git a/src/audacious/playlist-new.h b/src/audacious/playlist-new.h
index 0234946..92f75b8 100644
--- a/src/audacious/playlist-new.h
+++ b/src/audacious/playlist-new.h
@@ -50,6 +50,7 @@ void playlist_save_state (void);
gint playlist_count (void);
void playlist_insert (gint at);
+void playlist_reorder (gint from, gint to, gint count);
void playlist_delete (gint playlist);
void playlist_set_filename (gint playlist, const gchar * filename);
@@ -103,14 +104,13 @@ void playlist_sort_selected_by_filename (gint playlist, gint (* compare) (const
void playlist_sort_selected_by_tuple (gint playlist, gint (* compare) (const
Tuple * a, const Tuple * b));
-void playlist_reformat_titles ();
+void playlist_reformat_titles (void);
void playlist_rescan (gint playlist);
+void playlist_rescan_file (const gchar * filename);
gint64 playlist_get_total_length (gint playlist);
gint64 playlist_get_selected_length (gint playlist);
-void playlist_set_shuffle (gboolean shuffle);
-
gint playlist_queue_count (gint playlist);
void playlist_queue_insert (gint playlist, gint at, gint entry);
void playlist_queue_insert_selected (gint playlist, gint at);
diff --git a/src/audacious/playlist-utils.c b/src/audacious/playlist-utils.c
index ec389fa..430ce30 100644
--- a/src/audacious/playlist-utils.c
+++ b/src/audacious/playlist-utils.c
@@ -1,6 +1,6 @@
/*
* playlist-utils.c
- * Copyright 2009 John Lindgren
+ * Copyright 2009-2010 John Lindgren
*
* This file is part of Audacious.
*
@@ -320,3 +320,69 @@ gboolean playlist_save (gint playlist, const gchar * filename)
playlist_set_active (last);
return TRUE;
}
+
+/* The algorithm is a bit quirky for historical reasons. -jlindgren */
+static gchar * make_playlist_path (gint playlist)
+{
+ if (! playlist)
+ return g_strdup (aud_paths[BMP_PATH_PLAYLIST_FILE]);
+
+ return g_strdup_printf ("%s/playlist_%02d.xspf",
+ aud_paths[BMP_PATH_PLAYLISTS_DIR], 1 + playlist);
+}
+
+void load_playlists (void)
+{
+ gboolean done = FALSE;
+ gint count;
+
+ for (count = 0; ! done; count ++)
+ {
+ gchar * path = make_playlist_path (count);
+
+ if (g_file_test (path, G_FILE_TEST_EXISTS))
+ {
+ gchar * uri = g_filename_to_uri (path, NULL, NULL);
+
+ if (count)
+ playlist_insert (count);
+
+ playlist_insert_playlist (count, 0, uri);
+ g_free (uri);
+ }
+ else
+ done = TRUE;
+
+ g_free (path);
+ }
+
+ playlist_load_state ();
+}
+
+void save_playlists (void)
+{
+ gint playlists = playlist_count ();
+ gboolean done = FALSE;
+ gint count;
+
+ for (count = 0; ! done; count ++)
+ {
+ gchar * path = make_playlist_path (count);
+
+ if (count < playlists)
+ {
+ gchar * uri = g_filename_to_uri (path, NULL, NULL);
+
+ playlist_save (count, uri);
+ g_free (uri);
+ }
+ else if (g_file_test (path, G_FILE_TEST_EXISTS))
+ remove (path);
+ else
+ done = TRUE;
+
+ g_free (path);
+ }
+
+ playlist_save_state ();
+}
diff --git a/src/audacious/playlist-utils.h b/src/audacious/playlist-utils.h
index e5b8c87..69502ee 100644
--- a/src/audacious/playlist-utils.h
+++ b/src/audacious/playlist-utils.h
@@ -41,4 +41,7 @@ void playlist_insert_folder (gint playlist, gint at, const gchar * folder);
void playlist_insert_folder_v2 (gint playlist, gint at, const gchar * folder,
gboolean play);
+void save_playlists (void);
+void load_playlists (void);
+
#endif
diff --git a/src/audacious/plugin.h b/src/audacious/plugin.h
index 5c195b6..01bc054 100644
--- a/src/audacious/plugin.h
+++ b/src/audacious/plugin.h
@@ -1,5 +1,5 @@
/* Audacious
- * Copyright (C) 2005-2009 Audacious team.
+ * Copyright (C) 2005-2010 Audacious team.
*
* BMP - Cross-platform multimedia player
* Copyright (C) 2003-2004 BMP development team.
@@ -40,7 +40,7 @@
#define AUDACIOUS_PLUGIN_H
#include <glib.h>
-#include <gtk/gtk.h>
+#include <gmodule.h>
#include "libaudcore/audio.h"
#include "libaudcore/audstrings.h"
@@ -55,7 +55,6 @@
#include "audacious/preferences.h"
#include "audacious/interface.h"
#include "audacious/equalizer_preset.h"
-#include "libaudtag/audtag.h"
//@{
/** Plugin type cast macros */
@@ -65,13 +64,12 @@
#define EFFECT_PLUGIN(x) ((EffectPlugin *)(x))
#define GENERAL_PLUGIN(x) ((GeneralPlugin *)(x))
#define VIS_PLUGIN(x) ((VisPlugin *)(x))
-#define LOWLEVEL_PLUGIN(x) ((LowlevelPlugin *)(x))
//@}
//@{
/** Preprocessor defines for different API features */
#define __AUDACIOUS_NEWVFS__ /**< @deprecated define for availability of VFS API. */
-#define __AUDACIOUS_PLUGIN_API__ 13 /**< Current generic plugin API/ABI version, exact match is required for plugin to be loaded. */
+#define __AUDACIOUS_PLUGIN_API__ 14 /**< Current generic plugin API/ABI version, exact match is required for plugin to be loaded. */
#define __AUDACIOUS_INPUT_PLUGIN_API__ 8 /**< Input plugin API version. */
//@}
@@ -82,6 +80,12 @@ typedef enum {
INPUT_VIS_OFF
} InputVisType;
+typedef enum {
+ PLUGIN_MESSAGE_ERROR = 0,
+ PLUGIN_MESSAGE_OK = 1,
+ PLUGIN_MESSAGE_DEFERRED = 2
+} PluginMessageResponse;
+
/** Playlist update signal types */
enum
{
@@ -101,13 +105,14 @@ enum {
PLAYLIST_SORT_SCHEMES
};
+#define EQUALIZER_MAX_GAIN 12
+
typedef struct _Plugin Plugin;
typedef struct _InputPlugin InputPlugin;
typedef struct _OutputPlugin OutputPlugin;
typedef struct _EffectPlugin EffectPlugin;
typedef struct _GeneralPlugin GeneralPlugin;
typedef struct _VisPlugin VisPlugin;
-typedef struct _LowlevelPlugin LowlevelPlugin;
typedef struct _InputPlayback InputPlayback;
@@ -134,8 +139,8 @@ typedef struct {
gint api_version; /**< API version plugin has been compiled for,
this is checked against __AUDACIOUS_PLUGIN_API__ */
gchar *name; /**< Module name */
- GCallback init;
- GCallback fini;
+ void (* init) (void);
+ void (* fini) (void);
Plugin *priv_assoc;
InputPlugin **ip_list; /**< List of InputPlugin(s) in this module */
OutputPlugin **op_list;
@@ -166,47 +171,62 @@ typedef struct {
struct _AudaciousFuncTableV1 {
/* VFS */
- VFSFile *(*vfs_fopen)(const gchar *uri, const gchar *mode);
- gint (*vfs_fclose)(VFSFile *fd);
- VFSFile *(*vfs_dup)(VFSFile *in);
- gsize (*vfs_fread)(gpointer ptr,
- gsize size,
- gsize nmemb,
- VFSFile * file);
- gsize (*vfs_fwrite)(gconstpointer ptr,
- gsize size,
- gsize nmemb,
- VFSFile *file);
-
- gint (*vfs_getc)(VFSFile *stream);
- gint (*vfs_ungetc)(gint c,
- VFSFile *stream);
- gchar *(*vfs_fgets)(gchar *s,
- gint n,
- VFSFile *stream);
-
- gint (*vfs_fseek)(VFSFile * file,
- glong offset,
- gint whence);
- void (*vfs_rewind)(VFSFile * file);
- glong (*vfs_ftell)(VFSFile * file);
- gboolean (*vfs_feof)(VFSFile * file);
-
- gboolean (*vfs_file_test)(const gchar * path,
- GFileTest test);
-
- gboolean (*vfs_is_writeable)(const gchar * path);
- gboolean (*vfs_truncate)(VFSFile * file, glong length);
- off_t (*vfs_fsize)(VFSFile * file);
- gchar *(*vfs_get_metadata)(VFSFile * file, const gchar * field);
-
- int (*vfs_fprintf)(VFSFile *stream, gchar const *format, ...)
- __attribute__ ((__format__ (__printf__, 2, 3)));
-
- gboolean (*vfs_register_transport)(VFSConstructor *vtable);
- void (*vfs_file_get_contents)(const gchar *filename, gchar **buf, gsize *size);
- gboolean (*vfs_is_remote)(const gchar * path);
- gboolean (*vfs_is_streaming)(VFSFile *file);
+#ifdef __GNUC__
+#define WARN_RETURN __attribute__ ((warn_unused_result))
+#else
+#define WARN_RETURN
+#endif
+
+ VFSFile * (* vfs_fopen) (const gchar * path, const gchar * mode) WARN_RETURN;
+ VFSFile * (* vfs_dup) (VFSFile * in) WARN_RETURN;
+ gint (* vfs_fclose) (VFSFile * file);
+
+ gint64 (* vfs_fread) (void * ptr, gint64 size, gint64 nmemb, VFSFile *
+ file) WARN_RETURN;
+ gint64 (* vfs_fwrite) (const void * ptr, gint64 size, gint64 nmemb,
+ VFSFile * file) WARN_RETURN;
+
+ gint (* vfs_getc) (VFSFile * stream) WARN_RETURN;
+ gint (* vfs_ungetc) (gint c, VFSFile * stream) WARN_RETURN;
+ gchar * (* vfs_fgets) (gchar * s, gint n, VFSFile * stream) WARN_RETURN;
+ gboolean (* vfs_feof) (VFSFile * file) WARN_RETURN;
+ gint (* vfs_fprintf) (VFSFile * stream, gchar const * format, ...)
+ __attribute__ ((__format__ (__printf__, 2, 3)));
+
+ gint (* vfs_fseek) (VFSFile * file, gint64 offset, gint whence) WARN_RETURN;
+ void (* vfs_rewind) (VFSFile * file);
+ glong (* vfs_ftell) (VFSFile * file) WARN_RETURN;
+ gint64 (* vfs_fsize) (VFSFile * file) WARN_RETURN;
+ gint (* vfs_ftruncate) (VFSFile * file, gint64 length) WARN_RETURN;
+
+ gboolean (* vfs_fget_le16) (guint16 * value, VFSFile * stream) WARN_RETURN;
+ gboolean (* vfs_fget_le32) (guint32 * value, VFSFile * stream) WARN_RETURN;
+ gboolean (* vfs_fget_le64) (guint64 * value, VFSFile * stream) WARN_RETURN;
+ gboolean (* vfs_fget_be16) (guint16 * value, VFSFile * stream) WARN_RETURN;
+ gboolean (* vfs_fget_be32) (guint32 * value, VFSFile * stream) WARN_RETURN;
+ gboolean (* vfs_fget_be64) (guint64 * value, VFSFile * stream) WARN_RETURN;
+
+ gboolean (* vfs_fput_le16) (guint16 value, VFSFile * stream) WARN_RETURN;
+ gboolean (* vfs_fput_le32) (guint32 value, VFSFile * stream) WARN_RETURN;
+ gboolean (* vfs_fput_le64) (guint64 value, VFSFile * stream) WARN_RETURN;
+ gboolean (* vfs_fput_be16) (guint16 value, VFSFile * stream) WARN_RETURN;
+ gboolean (* vfs_fput_be32) (guint32 value, VFSFile * stream) WARN_RETURN;
+ gboolean (* vfs_fput_be64) (guint64 value, VFSFile * stream) WARN_RETURN;
+
+ gboolean (* vfs_is_streaming) (VFSFile * file) WARN_RETURN;
+ gchar * (* vfs_get_metadata) (VFSFile * file, const gchar * field)
+ WARN_RETURN;
+
+ gboolean (* vfs_file_test) (const gchar * path, GFileTest test) WARN_RETURN;
+ gboolean (* vfs_is_writeable) (const gchar * path) WARN_RETURN;
+ gboolean (* vfs_is_remote) (const gchar * path) WARN_RETURN;
+
+ void (* vfs_file_get_contents) (const gchar * filename, guchar * * buf,
+ gint64 * size);
+
+ void (* vfs_register_transport) (VFSConstructor * vtable);
+
+#undef WARN_RETURN
/* VFS Buffer */
VFSFile *(*vfs_buffer_new)(gpointer data, gsize size);
@@ -216,21 +236,6 @@ struct _AudaciousFuncTableV1 {
VFSFile *(*vfs_buffered_file_new_from_uri)(const gchar *uri);
VFSFile *(*vfs_buffered_file_release_live_fd)(VFSFile *fd);
- /* VFS endianess helper functions */
- gboolean (*vfs_fget_le16)(guint16 *value, VFSFile *stream);
- gboolean (*vfs_fget_le32)(guint32 *value, VFSFile *stream);
- gboolean (*vfs_fget_le64)(guint64 *value, VFSFile *stream);
- gboolean (*vfs_fget_be16)(guint16 *value, VFSFile *stream);
- gboolean (*vfs_fget_be32)(guint32 *value, VFSFile *stream);
- gboolean (*vfs_fget_be64)(guint64 *value, VFSFile *stream);
-
- gboolean (*vfs_fput_le16)(guint16 value, VFSFile *stream);
- gboolean (*vfs_fput_le32)(guint32 value, VFSFile *stream);
- gboolean (*vfs_fput_le64)(guint64 value, VFSFile *stream);
- gboolean (*vfs_fput_be16)(guint16 value, VFSFile *stream);
- gboolean (*vfs_fput_be32)(guint32 value, VFSFile *stream);
- gboolean (*vfs_fput_be64)(guint64 value, VFSFile *stream);
-
/* ConfigDb */
mcs_handle_t *(*cfg_db_open)(void);
void (*cfg_db_close)(mcs_handle_t *db);
@@ -286,14 +291,8 @@ struct _AudaciousFuncTableV1 {
void (* mime_set_plugin) (const gchar * mimetype, InputPlugin * ip);
/* Util funcs */
- GtkWidget *(*util_info_dialog)(const gchar * title, const gchar * text,
- const gchar * button_text, gboolean modal,
- GCallback button_action,
- gpointer action_data);
gchar *(*util_get_localdir)(void);
void (*util_menu_main_show)(gint x, gint y, guint button, guint time);
-
- gpointer (*smart_realloc)(gpointer ptr, gsize *size);
void (*util_add_url_history_entry)(const gchar * url);
/* INI funcs */
@@ -321,6 +320,7 @@ struct _AudaciousFuncTableV1 {
/* Playlist API II (core) */
gint (* playlist_count) (void);
void (* playlist_insert) (gint at);
+ void (* playlist_reorder) (gint from, gint to, gint count);
void (* playlist_delete) (gint playlist);
void (* playlist_set_filename) (gint playlist, const gchar * filename);
@@ -376,8 +376,6 @@ struct _AudaciousFuncTableV1 {
gint64 (* playlist_get_total_length) (gint playlist);
gint64 (* playlist_get_selected_length) (gint playlist);
- void (* playlist_set_shuffle) (gboolean shuffle);
-
gint (* playlist_queue_count) (gint playlist);
void (* playlist_queue_insert) (gint playlist, gint at, gint entry);
void (* playlist_queue_insert_selected) (gint playlist, gint at);
@@ -406,7 +404,8 @@ struct _AudaciousFuncTableV1 {
gboolean (* playlist_save) (gint playlist, const gchar * filename);
void (* playlist_insert_folder) (gint playlist, gint at, const gchar *
folder);
- void (* save_all_playlists) (void);
+ void (* playlist_insert_folder_v2) (gint playlist, gint at, const gchar *
+ folder, gboolean play);
/* state vars */
AudConfig *_cfg;
@@ -419,8 +418,10 @@ struct _AudaciousFuncTableV1 {
void (*hook_call)(const gchar *name, gpointer hook_data);
/* PluginMenu API */
- gint (*menu_plugin_item_add)(gint, GtkWidget *);
- gint (*menu_plugin_item_remove)(gint, GtkWidget *);
+ /* gint (* menu_plugin_item_add) (gint menu, GtkWidget * item); */
+ gint (* menu_plugin_item_add) (gint menu, void * item);
+ /* gint (* menu_plugin_item_remove) (gint, GtkWidget * item); */
+ gint (* menu_plugin_item_remove) (gint, void * item);
/* DRCT API. */
void (*drct_quit) ( void );
@@ -485,18 +486,6 @@ struct _AudaciousFuncTableV1 {
gint (*drct_pq_get_position)( gint pos );
gint (*drct_pq_get_queue_position)( gint pos );
- /* FileInfoPopup API */
- GtkWidget *(*fileinfopopup_create)(void);
- void (*fileinfopopup_destroy)(GtkWidget* fileinfopopup_win);
- void (*fileinfopopup_show_from_tuple)(GtkWidget *fileinfopopup_win, Tuple *tuple);
- void (*fileinfopopup_show_from_title)(GtkWidget *fileinfopopup_win, gchar *title);
- void (*fileinfopopup_hide)(GtkWidget *filepopup_win, gpointer unused);
-
- /* InputPlayback */
- InputPlayback *(*playback_new)(void);
- void (*playback_free)(InputPlayback *);
- void (*playback_run)(InputPlayback *);
-
/* Flows */
gsize (*flow_execute)(Flow *flow, gint time, gpointer *data, gsize len, AFormat fmt,
gint srate, gint channels);
@@ -525,7 +514,9 @@ struct _AudaciousFuncTableV1 {
void (*calc_mono_pcm)(gint16 dest[2][512], gint16 src[2][512], gint nch);
void (*calc_stereo_pcm)(gint16 dest[2][512], gint16 src[2][512], gint nch);
- void (* create_widgets_with_domain) (GtkBox * box, PreferencesWidget *
+ /* void (* create_widgets_with_domain) (GtkBox * box, PreferencesWidget *
+ widgets, gint amt, const gchar * domain); */
+ void (* create_widgets_with_domain) (void * box, PreferencesWidget *
widgets, gint amt, const gchar * domain);
GList *(*equalizer_read_presets)(const gchar * basename);
@@ -535,15 +526,23 @@ struct _AudaciousFuncTableV1 {
EqualizerPreset *(*equalizer_read_aud_preset)(const gchar * filename);
EqualizerPreset *(*load_preset_file)(const gchar *filename);
-// /* Audtag lib functions */
-// Tuple *(*tag_tuple_read)(Tuple* tuple);
-// gint (*tag_tuple_write_to_file)(Tuple *tuple);
+ /* File probing API */
+ InputPlugin * (* file_find_decoder) (const gchar * filename, gboolean fast);
+ Tuple * (* file_read_tuple) (const gchar * filename, InputPlugin * decoder);
+ gboolean (* file_read_image) (const gchar * filename, InputPlugin * decoder,
+ void * * data, gint * size);
+ gboolean (* file_can_write_tuple) (const gchar * filename, InputPlugin *
+ decoder);
+ gboolean (* file_write_tuple) (const gchar * filename, InputPlugin *
+ decoder, Tuple * tuple);
+ gboolean (* custom_infowin) (const gchar * filename, InputPlugin * decoder);
/* Miscellaneous */
- GtkWidget * (* get_plugin_menu) (gint id);
+ /* GtkWidget * (* get_plugin_menu) (gint id); */
+ void * (* get_plugin_menu) (gint id);
gchar * (* playback_get_title) (void);
- void (* fileinfo_show) (gint playlist, gint entry);
- void (* fileinfo_show_current) (void);
+ void (* save_all_playlists) (void);
+ gchar * (* get_associated_image_file) (const gchar * filename);
/* Interface API */
const Interface * (* interface_get_current) (void);
@@ -556,57 +555,52 @@ struct _AudaciousFuncTableV1 {
gboolean (* playlist_entry_is_segmented)(gint playlist_num, gint entry_num);
gint (* playlist_entry_get_start_time)(gint playlist_num, gint entry_num);
gint (* playlist_entry_get_end_time)(gint playlist_num, gint entry_num);
-
- /* Move to proper place when API can be broken */
- void (* playlist_insert_folder_v2) (gint playlist, gint at, const gchar *
- folder, gboolean play);
};
/* Convenience macros for accessing the public API. */
-/* public name vtable mapping */
+/* public name vtable mapping */
+
#define aud_vfs_fopen _audvt->vfs_fopen
-#define aud_vfs_fclose _audvt->vfs_fclose
#define aud_vfs_dup _audvt->vfs_dup
+#define aud_vfs_fclose _audvt->vfs_fclose
#define aud_vfs_fread _audvt->vfs_fread
#define aud_vfs_fwrite _audvt->vfs_fwrite
#define aud_vfs_getc _audvt->vfs_getc
#define aud_vfs_ungetc _audvt->vfs_ungetc
#define aud_vfs_fgets _audvt->vfs_fgets
+#define aud_vfs_feof _audvt->vfs_feof
+#define aud_vfs_fprintf _audvt->vfs_fprintf
#define aud_vfs_fseek _audvt->vfs_fseek
#define aud_vfs_rewind _audvt->vfs_rewind
#define aud_vfs_ftell _audvt->vfs_ftell
-#define aud_vfs_feof _audvt->vfs_feof
-#define aud_vfs_file_test _audvt->vfs_file_test
-#define aud_vfs_is_writeable _audvt->vfs_is_writeable
-#define aud_vfs_truncate _audvt->vfs_truncate
#define aud_vfs_fsize _audvt->vfs_fsize
-#define aud_vfs_get_metadata _audvt->vfs_get_metadata
-#define aud_vfs_fprintf _audvt->vfs_fprintf
-#define aud_vfs_register_transport _audvt->vfs_register_transport
-#define aud_vfs_file_get_contents _audvt->vfs_file_get_contents
-#define aud_vfs_is_remote _audvt->vfs_is_remote
-#define aud_vfs_is_streaming _audvt->vfs_is_streaming
-
-#define aud_vfs_buffer_new _audvt->vfs_buffer_new
-#define aud_vfs_buffer_new_from_string _audvt->vfs_buffer_new_from_string
-
-#define aud_vfs_buffered_file_new_from_uri _audvt->vfs_buffered_file_new_from_uri
-#define aud_vfs_buffered_file_release_live_fd _audvt->vfs_buffered_file_release_live_fd
-
+#define aud_vfs_ftruncate _audvt->vfs_ftruncate
#define aud_vfs_fget_le16 _audvt->vfs_fget_le16
#define aud_vfs_fget_le32 _audvt->vfs_fget_le32
#define aud_vfs_fget_le64 _audvt->vfs_fget_le64
#define aud_vfs_fget_be16 _audvt->vfs_fget_be16
#define aud_vfs_fget_be32 _audvt->vfs_fget_be32
#define aud_vfs_fget_be64 _audvt->vfs_fget_be64
-
#define aud_vfs_fput_le16 _audvt->vfs_fput_le16
#define aud_vfs_fput_le32 _audvt->vfs_fput_le32
#define aud_vfs_fput_le64 _audvt->vfs_fput_le64
#define aud_vfs_fput_be16 _audvt->vfs_fput_be16
#define aud_vfs_fput_be32 _audvt->vfs_fput_be32
#define aud_vfs_fput_be64 _audvt->vfs_fput_be64
+#define aud_vfs_is_streaming _audvt->vfs_is_streaming
+#define aud_vfs_get_metadata _audvt->vfs_get_metadata
+#define aud_vfs_file_test _audvt->vfs_file_test
+#define aud_vfs_is_writeable _audvt->vfs_is_writeable
+#define aud_vfs_is_remote _audvt->vfs_is_remote
+#define aud_vfs_file_get_contents _audvt->vfs_file_get_contents
+#define aud_vfs_register_transport _audvt->vfs_register_transport
+
+#define aud_vfs_buffer_new _audvt->vfs_buffer_new
+#define aud_vfs_buffer_new_from_string _audvt->vfs_buffer_new_from_string
+
+#define aud_vfs_buffered_file_new_from_uri _audvt->vfs_buffered_file_new_from_uri
+#define aud_vfs_buffered_file_release_live_fd _audvt->vfs_buffered_file_release_live_fd
/* XXX: deprecation warnings */
#define ConfigDb mcs_handle_t /* Alias for compatibility -- ccr */
@@ -649,9 +643,6 @@ struct _AudaciousFuncTableV1 {
#define aud_mime_set_plugin _audvt->mime_set_plugin
#define aud_uri_set_plugin _audvt->uri_set_plugin
-#define aud_info_dialog _audvt->util_info_dialog
-#define audacious_info_dialog _audvt->util_info_dialog
-#define aud_smart_realloc _audvt->smart_realloc
#define aud_util_add_url_history_entry _audvt->util_add_url_history_entry
#define aud_str_to_utf8 _audvt->str_to_utf8
@@ -678,6 +669,7 @@ struct _AudaciousFuncTableV1 {
#define aud_playlist_count _audvt->playlist_count
#define aud_playlist_insert _audvt->playlist_insert
+#define aud_playlist_reorder _audvt->playlist_reorder
#define aud_playlist_delete _audvt->playlist_delete
#define aud_playlist_set_filename _audvt->playlist_set_filename
@@ -726,7 +718,6 @@ struct _AudaciousFuncTableV1 {
#define aud_playlist_rescan _audvt->playlist_rescan
#define aud_playlist_get_total_length _audvt->playlist_get_total_length
#define aud_playlist_get_selected_length _audvt->playlist_get_selected_length
-#define aud_playlist_set_shuffle _audvt->playlist_set_shuffle
#define aud_playlist_queue_count _audvt->playlist_queue_count
#define aud_playlist_queue_insert _audvt->playlist_queue_insert
@@ -833,18 +824,8 @@ struct _AudaciousFuncTableV1 {
#define audacious_drct_pq_get_position _audvt->drct_pq_get_position
#define audacious_drct_pq_get_queue_position _audvt->drct_pq_get_queue_position
-#define audacious_fileinfopopup_create _audvt->fileinfopopup_create
-#define audacious_fileinfopopup_destroy _audvt->fileinfopopup_destroy
-#define audacious_fileinfopopup_show_from_tuple _audvt->fileinfopopup_show_from_tuple
-#define audacious_fileinfopopup_show_from_title _audvt->fileinfopopup_show_from_title
-#define audacious_fileinfopopup_hide _audvt->fileinfopopup_hide
-
#define audacious_get_localdir _audvt->util_get_localdir
-#define aud_playback_new _audvt->playback_new
-#define aud_playback_run _audvt->playback_run
-#define aud_playback_free(x) _audvt->playback_free
-
#define aud_flow_execute _audvt->flow_execute
#define aud_flow_new _audvt->flow_new
#define aud_flow_link_element _audvt->flow_link_element
@@ -894,14 +875,17 @@ struct _AudaciousFuncTableV1 {
#define aud_output_plugin_cleanup _audvt->output_plugin_cleanup
#define aud_output_plugin_reinit _audvt->output_plugin_reinit
+#define aud_file_find_decoder _audvt->file_find_decoder
+#define aud_file_read_tuple _audvt->file_read_tuple
+#define aud_file_read_image _audvt->file_read_image
+#define aud_file_can_write_tuple _audvt->file_can_write_tuple
+#define aud_file_write_tuple _audvt->file_write_tuple
+#define aud_custom_infowin _audvt->custom_infowin
+
#define aud_get_plugin_menu _audvt->get_plugin_menu
#define aud_playback_get_title _audvt->playback_get_title
-#define aud_fileinfo_show _audvt->fileinfo_show
-#define aud_fileinfo_show_current _audvt->fileinfo_show_current
#define aud_save_all_playlists _audvt->save_all_playlists
-
-//#define aud_tag_tuple_read _audvt->tag_tuple_read
-//#define aud_tag_tuple_write_to_file _audvt->tag_tuple_write
+#define aud_get_associated_image_file _audvt->get_associated_image_file
#define aud_interface_get_current _audvt->interface_get_current
#define aud_interface_toggle_visibility _audvt->interface_toggle_visibility
@@ -914,6 +898,7 @@ struct _AudaciousFuncTableV1 {
#define aud_playlist_entry_get_start_time _audvt->playlist_entry_get_start_time
#define aud_playlist_entry_get_end_time _audvt->playlist_entry_get_end_time
+
#include "audacious/auddrct.h"
/* for multi-file plugins :( */
@@ -959,7 +944,8 @@ G_END_DECLS
void (*cleanup) (void); \
void (*about) (void); \
void (*configure) (void); \
- PluginPreferences *settings;
+ PluginPreferences *settings; \
+ PluginMessageResponse (*sendmsg)(gint msgtype, gpointer msgdata);
/* Sadly, this is the most we can generalize out of the disparate
plugin structs usable with typecasts - descender */
@@ -967,18 +953,6 @@ struct _Plugin {
PLUGIN_COMMON_FIELDS
};
-/*
- * LowlevelPlugin is used for lowlevel system services, such as PlaylistContainers,
- * VFSContainers and the like.
- *
- * They are not GUI visible at this time.
- *
- * XXX: Is this still in use in 1.4? --nenolod
- */
-struct _LowlevelPlugin {
- PLUGIN_COMMON_FIELDS
-};
-
typedef enum {
OUTPUT_PLUGIN_INIT_FAIL,
OUTPUT_PLUGIN_INIT_NO_DEVICES,
@@ -1041,16 +1015,20 @@ struct _EffectPlugin {
void (* process) (gfloat * * data, gint * samples);
/* A seek is taking place; any buffers should be discarded. */
- void (* flush) ();
+ void (* flush) (void);
/* Exactly like process() except that any buffers should be drained (i.e.
- * the data processed and returned). */
+ * the data processed and returned). finish() will be called a second time
+ * at the end of the last song in the playlist. */
void (* finish) (gfloat * * data, gint * samples);
/* For effects that change the length of the song, these functions allow the
* correct time to be displayed. */
gint (* decoder_to_output_time) (gint time);
gint (* output_to_decoder_time) (gint time);
+
+ /* Effects with lowest order (0 to 9) are applied first. */
+ gint order;
};
struct OutputAPI
@@ -1101,12 +1079,6 @@ struct _InputPlayback {
void (*set_params) (InputPlayback * playback, const gchar * title, gint
length, gint bitrate, gint samplerate, gint channels);
- /**
- * Set playback entry title.
- * @deprecated This function is deprecated, use #set_tuple() instead.
- */
- void (*set_title) (InputPlayback * playback, const gchar * title);
-
void (*pass_audio) (InputPlayback *, AFormat, gint, gint, gpointer, gint *);
/* called by input plugin when RG info available --asphyx */
@@ -1123,6 +1095,12 @@ struct _InputPlayback {
gint start;
gint end;
gint end_timeout;
+
+ /* If replay gain settings are stored in the tuple associated with the
+ * current song, this function can be called (after opening audio) to apply
+ * those settings. If the settings are changed in a call to set_tuple, this
+ * function must be called again to apply the updated settings. */
+ void (* set_gain_from_playlist) (InputPlayback * playback);
};
/**
@@ -1175,6 +1153,11 @@ struct _InputPlugin {
gboolean (*update_song_tuple)(Tuple *tuple, VFSFile *fd);
gint priority; /* 0 = first, 10 = last */
+
+ /* handle will be NULL if the file could not be opened. This is normal in
+ * the case of custom URI schemes such as cdda://. */
+ gboolean (* get_song_image) (const gchar * filename, VFSFile * handle,
+ void * * data, gint * size);
};
struct _GeneralPlugin {
@@ -1203,7 +1186,8 @@ struct _VisPlugin {
*/
void (*render_freq) (gint16 freq_data[2][256]);
- GtkWidget *(*get_widget) (void);
+ /* GtkWidget * (* get_widget) (void); */
+ void * (* get_widget) (void);
};
/* undefine the macro -- struct Plugin should be used instead. */
diff --git a/src/audacious/pluginenum.c b/src/audacious/pluginenum.c
index 13559f4..9790648 100644
--- a/src/audacious/pluginenum.c
+++ b/src/audacious/pluginenum.c
@@ -51,6 +51,7 @@
#include "playback.h"
#include "playlist-new.h"
#include "playlist-utils.h"
+#include "probe.h"
#include "audstrings.h"
#include "util.h"
#include "visualization.h"
@@ -59,11 +60,12 @@
#include "vfs_buffered_file.h"
#include "equalizer_preset.h"
-#include "ui_fileinfo.h"
-#include "ui_fileinfopopup.h"
+#include "ui_albumart.h"
#include "ui_plugin_menu.h"
#include "ui_preferences.h"
+#include <libaudgui/init.h>
+
const gchar *plugin_dir_list[] = {
PLUGINSUBS,
@@ -77,47 +79,45 @@ static gpointer get_pvt_data(void);
static struct _AudaciousFuncTableV1 _aud_papi_v1 = {
.vfs_fopen = vfs_fopen,
- .vfs_fclose = vfs_fclose,
.vfs_dup = vfs_dup,
+ .vfs_fclose = vfs_fclose,
.vfs_fread = vfs_fread,
.vfs_fwrite = vfs_fwrite,
.vfs_getc = vfs_getc,
.vfs_ungetc = vfs_ungetc,
.vfs_fgets = vfs_fgets,
+ .vfs_feof = vfs_feof,
+ .vfs_fprintf = vfs_fprintf,
.vfs_fseek = vfs_fseek,
.vfs_rewind = vfs_rewind,
.vfs_ftell = vfs_ftell,
- .vfs_feof = vfs_feof,
- .vfs_file_test = vfs_file_test,
- .vfs_is_writeable = vfs_is_writeable,
- .vfs_truncate = vfs_truncate,
.vfs_fsize = vfs_fsize,
- .vfs_get_metadata = vfs_get_metadata,
- .vfs_fprintf = vfs_fprintf,
- .vfs_register_transport = vfs_register_transport,
- .vfs_file_get_contents = vfs_file_get_contents,
- .vfs_is_remote = vfs_is_remote,
- .vfs_is_streaming = vfs_is_streaming,
-
- .vfs_buffer_new = vfs_buffer_new,
- .vfs_buffer_new_from_string = vfs_buffer_new_from_string,
-
- .vfs_buffered_file_new_from_uri = vfs_buffered_file_new_from_uri,
- .vfs_buffered_file_release_live_fd = vfs_buffered_file_release_live_fd,
-
+ .vfs_ftruncate = vfs_ftruncate,
.vfs_fget_le16 = vfs_fget_le16,
.vfs_fget_le32 = vfs_fget_le32,
.vfs_fget_le64 = vfs_fget_le64,
.vfs_fget_be16 = vfs_fget_be16,
.vfs_fget_be32 = vfs_fget_be32,
.vfs_fget_be64 = vfs_fget_be64,
-
.vfs_fput_le16 = vfs_fput_le16,
.vfs_fput_le32 = vfs_fput_le32,
.vfs_fput_le64 = vfs_fput_le64,
.vfs_fput_be16 = vfs_fput_be16,
.vfs_fput_be32 = vfs_fput_be32,
.vfs_fput_be64 = vfs_fput_be64,
+ .vfs_is_streaming = vfs_is_streaming,
+ .vfs_get_metadata = vfs_get_metadata,
+ .vfs_file_test = vfs_file_test,
+ .vfs_is_writeable = vfs_is_writeable,
+ .vfs_is_remote = vfs_is_remote,
+ .vfs_file_get_contents = vfs_file_get_contents,
+ .vfs_register_transport = vfs_register_transport,
+
+ .vfs_buffer_new = vfs_buffer_new,
+ .vfs_buffer_new_from_string = vfs_buffer_new_from_string,
+
+ .vfs_buffered_file_new_from_uri = vfs_buffered_file_new_from_uri,
+ .vfs_buffered_file_release_live_fd = vfs_buffered_file_release_live_fd,
.cfg_db_open = cfg_db_open,
.cfg_db_close = cfg_db_close,
@@ -139,10 +139,6 @@ static struct _AudaciousFuncTableV1 _aud_papi_v1 = {
.uri_set_plugin = input_plugin_add_scheme_compat,
.mime_set_plugin = input_plugin_add_mime_compat,
- .util_info_dialog = util_info_dialog,
-
- .smart_realloc = smart_realloc,
-
.util_add_url_history_entry = util_add_url_history_entry,
.str_to_utf8 = cd_str_to_utf8,
@@ -156,6 +152,7 @@ static struct _AudaciousFuncTableV1 _aud_papi_v1 = {
.playlist_count = playlist_count,
.playlist_insert = playlist_insert,
+ .playlist_reorder = playlist_reorder,
.playlist_delete = playlist_delete,
.playlist_set_filename = playlist_set_filename,
@@ -204,8 +201,6 @@ static struct _AudaciousFuncTableV1 _aud_papi_v1 = {
.playlist_get_total_length = playlist_get_total_length,
.playlist_get_selected_length = playlist_get_selected_length,
- .playlist_set_shuffle = playlist_set_shuffle,
-
.playlist_queue_count = playlist_queue_count,
.playlist_queue_insert = playlist_queue_insert,
.playlist_queue_insert_selected = playlist_queue_insert_selected,
@@ -307,12 +302,6 @@ static struct _AudaciousFuncTableV1 _aud_papi_v1 = {
.drct_pq_get_position = drct_pq_get_position,
.drct_pq_get_queue_position = drct_pq_get_queue_position,
- .fileinfopopup_create = fileinfopopup_create,
- .fileinfopopup_destroy = fileinfopopup_destroy,
- .fileinfopopup_show_from_title = fileinfopopup_show_from_title,
- .fileinfopopup_show_from_tuple = fileinfopopup_show_from_tuple,
- .fileinfopopup_hide = fileinfopopup_hide,
-
.util_get_localdir = util_get_localdir,
.flow_new = flow_new,
@@ -349,11 +338,17 @@ static struct _AudaciousFuncTableV1 _aud_papi_v1 = {
.equalizer_read_aud_preset = equalizer_read_aud_preset,
.load_preset_file = load_preset_file,
+ .file_find_decoder = file_find_decoder,
+ .file_read_tuple = file_read_tuple,
+ .file_read_image = file_read_image,
+ .file_can_write_tuple = file_can_write_tuple,
+ .file_write_tuple = file_write_tuple,
+ .custom_infowin = custom_infowin,
+
.get_plugin_menu = get_plugin_menu,
.playback_get_title = playback_get_title,
- .fileinfo_show = ui_fileinfo_show,
- .fileinfo_show_current = ui_fileinfo_show_current,
- .save_all_playlists = save_all_playlists,
+ .save_all_playlists = save_playlists,
+ .get_associated_image_file = get_associated_image_file,
.interface_get_current = interface_get_current,
.interface_toggle_visibility = interface_toggle_visibility,
@@ -370,7 +365,6 @@ static struct _AudaciousFuncTableV1 _aud_papi_v1 = {
/*****************************************************************/
-GList *lowlevel_list = NULL;
extern GList *vfs_transports;
static GStaticPrivate cur_plugin_key = G_STATIC_PRIVATE_INIT;
@@ -616,9 +610,17 @@ void plugin2_unload(PluginHeader * header, mowgli_node_t * hlist_node)
{
if (header->ip_list[i]->cleanup != NULL)
header->ip_list[i]->cleanup ();
+
+ g_free (header->ip_list[i]->filename);
}
}
+ if (header->op_list != NULL)
+ {
+ for (i = 0; header->op_list[i] != NULL; i ++)
+ g_free (header->op_list[i]->filename);
+ }
+
if (header->interface)
interface_deregister(header->interface);
@@ -728,11 +730,12 @@ static OutputPlugin * output_probe (void)
void plugin_system_init(void)
{
gchar *dir;
- GList *node;
- LowlevelPlugin *lp;
GtkWidget *dialog;
gint dirsel = 0;
+ /* give libaudgui its pointer to the API vector table */
+ audgui_init (& _aud_papi_v1);
+
if (!g_module_supported())
{
dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, _("Module loading not supported! Plugins will not be loaded.\n"));
@@ -801,16 +804,6 @@ void plugin_system_init(void)
if (current_output_plugin == NULL)
current_output_plugin = output_probe ();
-
- for (node = lowlevel_list; node; node = g_list_next(node))
- {
- lp = LOWLEVEL_PLUGIN(node->data);
- if (lp->init)
- {
- plugin_set_current((Plugin *) lp);
- lp->init();
- }
- }
}
void plugin_system_cleanup(void)
@@ -818,7 +811,6 @@ void plugin_system_cleanup(void)
EffectPlugin *ep;
GeneralPlugin *gp;
VisPlugin *vp;
- LowlevelPlugin *lp;
GList *node;
mowgli_node_t *hlist_node;
@@ -846,6 +838,8 @@ void plugin_system_cleanup(void)
if (ep->cleanup)
ep->cleanup();
+
+ g_free (ep->filename);
GDK_THREADS_LEAVE();
while (g_main_context_iteration(NULL, FALSE));
@@ -869,6 +863,8 @@ void plugin_system_cleanup(void)
if (gp->cleanup)
gp->cleanup();
+ g_free (gp->filename);
+
GDK_THREADS_LEAVE();
while (g_main_context_iteration(NULL, FALSE));
GDK_THREADS_ENTER();
@@ -891,6 +887,8 @@ void plugin_system_cleanup(void)
if (vp->cleanup)
vp->cleanup();
+ g_free (vp->filename);
+
GDK_THREADS_LEAVE();
while (g_main_context_iteration(NULL, FALSE));
GDK_THREADS_ENTER();
@@ -903,28 +901,6 @@ void plugin_system_cleanup(void)
vp_data.vis_list = NULL;
}
- for (node = lowlevel_list; node; node = g_list_next(node))
- {
- lp = LOWLEVEL_PLUGIN(node->data);
- if (lp)
- {
- plugin_set_current((Plugin *) lp);
-
- if (lp->cleanup)
- lp->cleanup();
-
- GDK_THREADS_LEAVE();
- while (g_main_context_iteration(NULL, FALSE));
- GDK_THREADS_ENTER();
- }
- }
-
- if (lowlevel_list != NULL)
- {
- g_list_free(lowlevel_list);
- lowlevel_list = NULL;
- }
-
/* XXX: vfs will crash otherwise. -nenolod */
if (vfs_transports != NULL)
{
diff --git a/src/audacious/preferences.h b/src/audacious/preferences.h
index 0a8fddd..62d64c0 100644
--- a/src/audacious/preferences.h
+++ b/src/audacious/preferences.h
@@ -107,7 +107,9 @@ typedef struct _PreferencesWidget {
gboolean horizontal; /* FALSE gives vertical, TRUE gives horizontal separator */
} separator;
- GtkWidget *(*populate) (void); /* for WIDGET_CUSTOM --nenolod */
+ /* for WIDGET_CUSTOM --nenolod */
+ /* GtkWidget * (* populate) (void); */
+ void * (* populate) (void);
} data;
ValueType cfg_type; /* connected value type */
} PreferencesWidget;
@@ -140,7 +142,9 @@ typedef struct {
gpointer data; /* for internal interface use only */
} PluginPreferences;
-void create_widgets_with_domain (GtkBox * box, PreferencesWidget * widgets, gint
+/* void create_widgets_with_domain (GtkBox * box, PreferencesWidget * widgets,
+ gint amt, const gchar * domain); */
+void create_widgets_with_domain (void * box, PreferencesWidget * widgets, gint
amt, const gchar * domain);
#define create_widgets(b, w, a) create_widgets_with_domain (b, w, a, PACKAGE);
diff --git a/src/audacious/probe.c b/src/audacious/probe.c
index ea6b7bb..17c4b13 100644
--- a/src/audacious/probe.c
+++ b/src/audacious/probe.c
@@ -24,6 +24,7 @@
#include <stdio.h>
#include <string.h>
+#include "playlist-new.h"
#include "plugin-registry.h"
#include "probe.h"
@@ -63,7 +64,8 @@ static gboolean probe_func (InputPlugin * decoder, void * data)
if (decoder->is_our_file_from_vfs (state->filename, state->handle))
state->decoder = decoder;
- vfs_fseek (state->handle, 0, SEEK_SET);
+ if (vfs_fseek (state->handle, 0, SEEK_SET))
+ ; /* ignore errors; they are normal on streaming */
}
else if (decoder->is_our_file != NULL)
{
@@ -97,7 +99,8 @@ static gboolean probe_func_fast (InputPlugin * decoder, void * data)
state->handle))
return FALSE;
- vfs_fseek (state->handle, 0, SEEK_SET);
+ if (vfs_fseek (state->handle, 0, SEEK_SET))
+ ; /* ignore errors; they are normal on streaming */
}
else if (state->decoder->is_our_file != NULL)
{
@@ -163,7 +166,7 @@ static void probe_by_content (ProbeState * state)
input_plugin_by_priority (probe_func, state);
}
-InputPlugin * file_probe (const gchar * filename, gboolean fast)
+InputPlugin * file_find_decoder (const gchar * filename, gboolean fast)
{
ProbeState state;
@@ -197,3 +200,79 @@ DONE:
return state.decoder;
}
+
+Tuple * file_read_tuple (const gchar * filename, InputPlugin * decoder)
+{
+ if (decoder->get_song_tuple != NULL)
+ return decoder->get_song_tuple (filename);
+
+ if (decoder->probe_for_tuple != NULL)
+ {
+ VFSFile * handle = vfs_fopen (filename, "r");
+ Tuple * tuple;
+
+ if (handle == NULL)
+ return NULL;
+
+ tuple = decoder->probe_for_tuple (filename, handle);
+ vfs_fclose (handle);
+ return tuple;
+ }
+
+ return NULL;
+}
+
+gboolean file_read_image (const gchar * filename, InputPlugin * decoder,
+ void * * data, gint * size)
+{
+ VFSFile * handle;
+ gboolean success;
+
+ if (decoder->get_song_image == NULL)
+ return FALSE;
+
+ handle = vfs_fopen (filename, "r");
+ success = decoder->get_song_image (filename, handle, data, size);
+
+ if (handle != NULL)
+ vfs_fclose (handle);
+
+ return success;
+}
+
+gboolean file_can_write_tuple (const gchar * filename, InputPlugin * decoder)
+{
+ return (decoder->update_song_tuple != NULL);
+}
+
+gboolean file_write_tuple (const gchar * filename, InputPlugin * decoder,
+ Tuple * tuple)
+{
+ VFSFile * handle;
+ gboolean success;
+
+ if (decoder->update_song_tuple == NULL)
+ return FALSE;
+
+ handle = vfs_fopen (filename, "r+");
+
+ if (handle == NULL)
+ return FALSE;
+
+ success = decoder->update_song_tuple (tuple, handle);
+ vfs_fclose (handle);
+
+ if (success)
+ playlist_rescan_file (filename);
+
+ return success;
+}
+
+gboolean custom_infowin (const gchar * filename, InputPlugin * decoder)
+{
+ if (decoder->file_info_box == NULL)
+ return FALSE;
+
+ decoder->file_info_box (filename);
+ return TRUE;
+}
diff --git a/src/audacious/probe.h b/src/audacious/probe.h
index 5cb6d31..4a6971b 100644
--- a/src/audacious/probe.h
+++ b/src/audacious/probe.h
@@ -1,6 +1,6 @@
/*
* probe.h
- * Copyright 2009 John Lindgren
+ * Copyright 2009-2010 John Lindgren
*
* This file is part of Audacious.
*
@@ -24,6 +24,14 @@
#include "plugin.h"
-InputPlugin * file_probe (const gchar * filename, gboolean fast);
+InputPlugin * file_find_decoder (const gchar * filename, gboolean fast);
+Tuple * file_read_tuple (const gchar * filename, InputPlugin * decoder);
+gboolean file_read_image (const gchar * filename, InputPlugin * decoder,
+ void * * data, gint * size);
+gboolean file_can_write_tuple (const gchar * filename, InputPlugin * decoder);
+gboolean file_write_tuple (const gchar * filename, InputPlugin * decoder,
+ Tuple * tuple);
+
+gboolean custom_infowin (const gchar * filename, InputPlugin * decoder);
#endif
diff --git a/src/audacious/sync-menu.c b/src/audacious/sync-menu.c
deleted file mode 100644
index 5757b1c..0000000
--- a/src/audacious/sync-menu.c
+++ /dev/null
@@ -1,715 +0,0 @@
-/* GTK+ Integration for the Mac OS X Menubar.
- *
- * Copyright (C) 2007 Pioneer Research Center USA, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <gtk/gtk.h>
-
-#ifdef GDK_WINDOWING_QUARTZ
-
-#include <gdk/gdkkeysyms.h>
-
-#include <Carbon/Carbon.h>
-
-#include "sync-menu.h"
-
-
-/* TODO
- *
- * - Setup shortcuts, possibly transforming ctrl->cmd
- * - Sync menus
- * - Create on demand? (can this be done with gtk+? ie fill in menu items when the menu is opened)
- * - Figure out what to do per app/window...
- * - Toggle/radio items
- *
- */
-
-#define GTK_QUARTZ_MENU_CREATOR 'GTKC'
-#define GTK_QUARTZ_ITEM_WIDGET 'GWID'
-
-
-static void sync_menu_shell (GtkMenuShell *menu_shell,
- MenuRef carbon_menu,
- gboolean toplevel);
-
-
-/*
- * utility functions
- */
-
-static GtkWidget *
-find_menu_label (GtkWidget *widget)
-{
- GtkWidget *label = NULL;
-
- if (GTK_IS_LABEL (widget))
- return widget;
-
- if (GTK_IS_CONTAINER (widget))
- {
- GList *children;
- GList *l;
-
- children = gtk_container_get_children (GTK_CONTAINER (widget));
-
- for (l = children; l; l = l->next)
- {
- label = find_menu_label (l->data);
- if (label)
- break;
- }
-
- g_list_free (children);
- }
-
- return label;
-}
-
-static const gchar *
-get_menu_label_text (GtkWidget *menu_item,
- GtkWidget **label)
-{
- *label = find_menu_label (menu_item);
- if (!*label)
- return NULL;
-
- return gtk_label_get_text (GTK_LABEL (*label));
-}
-
-static gboolean
-accel_find_func (GtkAccelKey *key,
- GClosure *closure,
- gpointer data)
-{
- return (GClosure *) data == closure;
-}
-
-
-/*
- * CarbonMenu functions
- */
-
-typedef struct
-{
- MenuRef menu;
-} CarbonMenu;
-
-static GQuark carbon_menu_quark = 0;
-
-static CarbonMenu *
-carbon_menu_new (void)
-{
- return g_slice_new0 (CarbonMenu);
-}
-
-static void
-carbon_menu_free (CarbonMenu *menu)
-{
- g_slice_free (CarbonMenu, menu);
-}
-
-static CarbonMenu *
-carbon_menu_get (GtkWidget *widget)
-{
- return g_object_get_qdata (G_OBJECT (widget), carbon_menu_quark);
-}
-
-static void
-carbon_menu_connect (GtkWidget *menu,
- MenuRef menuRef)
-{
- CarbonMenu *carbon_menu = carbon_menu_get (menu);
-
- if (!carbon_menu)
- {
- carbon_menu = carbon_menu_new ();
-
- g_object_set_qdata_full (G_OBJECT (menu), carbon_menu_quark,
- carbon_menu,
- (GDestroyNotify) carbon_menu_free);
- }
-
- carbon_menu->menu = menuRef;
-}
-
-
-/*
- * CarbonMenuItem functions
- */
-
-typedef struct
-{
- MenuRef menu;
- MenuItemIndex index;
- MenuRef submenu;
- GClosure *accel_closure;
-} CarbonMenuItem;
-
-static GQuark carbon_menu_item_quark = 0;
-
-static CarbonMenuItem *
-carbon_menu_item_new (void)
-{
- return g_slice_new0 (CarbonMenuItem);
-}
-
-static void
-carbon_menu_item_free (CarbonMenuItem *menu_item)
-{
- if (menu_item->accel_closure)
- g_closure_unref (menu_item->accel_closure);
-
- g_slice_free (CarbonMenuItem, menu_item);
-}
-
-static CarbonMenuItem *
-carbon_menu_item_get (GtkWidget *widget)
-{
- return g_object_get_qdata (G_OBJECT (widget), carbon_menu_item_quark);
-}
-
-static void
-carbon_menu_item_update_state (CarbonMenuItem *carbon_item,
- GtkWidget *widget)
-{
- gboolean sensitive;
- gboolean visible;
- UInt32 set_attrs = 0;
- UInt32 clear_attrs = 0;
-
- g_object_get (widget,
- "sensitive", &sensitive,
- "visible", &visible,
- NULL);
-
- if (!sensitive)
- set_attrs |= kMenuItemAttrDisabled;
- else
- clear_attrs |= kMenuItemAttrDisabled;
-
- if (!visible)
- set_attrs |= kMenuItemAttrHidden;
- else
- clear_attrs |= kMenuItemAttrHidden;
-
- ChangeMenuItemAttributes (carbon_item->menu, carbon_item->index,
- set_attrs, clear_attrs);
-}
-
-static void
-carbon_menu_item_update_active (CarbonMenuItem *carbon_item,
- GtkWidget *widget)
-{
- gboolean active;
-
- g_object_get (widget,
- "active", &active,
- NULL);
-
- CheckMenuItem (carbon_item->menu, carbon_item->index,
- active);
-}
-
-static void
-carbon_menu_item_update_submenu (CarbonMenuItem *carbon_item,
- GtkWidget *widget)
-{
- GtkWidget *submenu;
-
- submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
-
- if (submenu)
- {
- GtkWidget *label = NULL;
- const gchar *label_text;
- CFStringRef cfstr = NULL;
-
- label_text = get_menu_label_text (widget, &label);
- if (label_text)
- cfstr = CFStringCreateWithCString (NULL, label_text,
- kCFStringEncodingUTF8);
-
- CreateNewMenu (0, 0, &carbon_item->submenu);
- SetMenuTitleWithCFString (carbon_item->submenu, cfstr);
- SetMenuItemHierarchicalMenu (carbon_item->menu, carbon_item->index,
- carbon_item->submenu);
-
- sync_menu_shell (GTK_MENU_SHELL (submenu), carbon_item->submenu, FALSE);
-
- if (cfstr)
- CFRelease (cfstr);
- }
- else
- {
- SetMenuItemHierarchicalMenu (carbon_item->menu, carbon_item->index,
- NULL);
- carbon_item->submenu = NULL;
- }
-}
-
-static void
-carbon_menu_item_update_label (CarbonMenuItem *carbon_item,
- GtkWidget *widget)
-{
- GtkWidget *label;
- const gchar *label_text;
- CFStringRef cfstr = NULL;
-
- label_text = get_menu_label_text (widget, &label);
- if (label_text)
- cfstr = CFStringCreateWithCString (NULL, label_text,
- kCFStringEncodingUTF8);
-
- SetMenuItemTextWithCFString (carbon_item->menu, carbon_item->index,
- cfstr);
-
- if (cfstr)
- CFRelease (cfstr);
-}
-
-static void
-carbon_menu_item_update_accelerator (CarbonMenuItem *carbon_item,
- GtkWidget *widget)
-{
- GtkWidget *label;
-
- get_menu_label_text (widget, &label);
-
- if (GTK_IS_ACCEL_LABEL (label) &&
- GTK_ACCEL_LABEL (label)->accel_closure)
- {
- GtkAccelKey *key;
-
- key = gtk_accel_group_find (GTK_ACCEL_LABEL (label)->accel_group,
- accel_find_func,
- GTK_ACCEL_LABEL (label)->accel_closure);
-
- if (key &&
- key->accel_key &&
- key->accel_flags & GTK_ACCEL_VISIBLE)
- {
- GdkDisplay *display = gtk_widget_get_display (widget);
- GdkKeymap *keymap = gdk_keymap_get_for_display (display);
- GdkKeymapKey *keys;
- gint n_keys;
-
- if (gdk_keymap_get_entries_for_keyval (keymap, key->accel_key,
- &keys, &n_keys))
- {
- UInt8 modifiers = 0;
-
- SetMenuItemCommandKey (carbon_item->menu, carbon_item->index,
- true, keys[0].keycode);
-
- g_free (keys);
-
- if (key->accel_mods)
- {
- if (key->accel_mods & GDK_SHIFT_MASK)
- modifiers |= kMenuShiftModifier;
-
- if (key->accel_mods & GDK_MOD1_MASK)
- modifiers |= kMenuOptionModifier;
- }
-
- if (!(key->accel_mods & GDK_CONTROL_MASK))
- {
- modifiers |= kMenuNoCommandModifier;
- }
-
- SetMenuItemModifiers (carbon_item->menu, carbon_item->index,
- modifiers);
-
- return;
- }
- }
- }
-
- /* otherwise, clear the menu shortcut */
- SetMenuItemModifiers (carbon_item->menu, carbon_item->index,
- kMenuNoModifiers | kMenuNoCommandModifier);
- ChangeMenuItemAttributes (carbon_item->menu, carbon_item->index,
- 0, kMenuItemAttrUseVirtualKey);
- SetMenuItemCommandKey (carbon_item->menu, carbon_item->index,
- false, 0);
-}
-
-static void
-carbon_menu_item_accel_changed (GtkAccelGroup *accel_group,
- guint keyval,
- GdkModifierType modifier,
- GClosure *accel_closure,
- GtkWidget *widget)
-{
- CarbonMenuItem *carbon_item = carbon_menu_item_get (widget);
- GtkWidget *label;
-
- get_menu_label_text (widget, &label);
-
- if (GTK_IS_ACCEL_LABEL (label) &&
- GTK_ACCEL_LABEL (label)->accel_closure == accel_closure)
- carbon_menu_item_update_accelerator (carbon_item, widget);
-}
-
-static void
-carbon_menu_item_update_accel_closure (CarbonMenuItem *carbon_item,
- GtkWidget *widget)
-{
- GtkAccelGroup *group;
- GtkWidget *label;
-
- get_menu_label_text (widget, &label);
-
- if (carbon_item->accel_closure)
- {
- group = gtk_accel_group_from_accel_closure (carbon_item->accel_closure);
-
- g_signal_handlers_disconnect_by_func (group,
- carbon_menu_item_accel_changed,
- widget);
-
- g_closure_unref (carbon_item->accel_closure);
- carbon_item->accel_closure = NULL;
- }
-
- if (GTK_IS_ACCEL_LABEL (label))
- carbon_item->accel_closure = GTK_ACCEL_LABEL (label)->accel_closure;
-
- if (carbon_item->accel_closure)
- {
- g_closure_ref (carbon_item->accel_closure);
-
- group = gtk_accel_group_from_accel_closure (carbon_item->accel_closure);
-
- g_signal_connect_object (group, "accel-changed",
- G_CALLBACK (carbon_menu_item_accel_changed),
- widget, 0);
- }
-
- carbon_menu_item_update_accelerator (carbon_item, widget);
-}
-
-static void
-carbon_menu_item_notify (GObject *object,
- GParamSpec *pspec,
- CarbonMenuItem *carbon_item)
-{
- if (!strcmp (pspec->name, "sensitive") ||
- !strcmp (pspec->name, "visible"))
- {
- carbon_menu_item_update_state (carbon_item, GTK_WIDGET (object));
- }
- else if (!strcmp (pspec->name, "active"))
- {
- carbon_menu_item_update_active (carbon_item, GTK_WIDGET (object));
- }
- else if (!strcmp (pspec->name, "submenu"))
- {
- carbon_menu_item_update_submenu (carbon_item, GTK_WIDGET (object));
- }
-}
-
-static void
-carbon_menu_item_notify_label (GObject *object,
- GParamSpec *pspec,
- gpointer data)
-{
- CarbonMenuItem *carbon_item = carbon_menu_item_get (GTK_WIDGET (object));
-
- if (!strcmp (pspec->name, "label"))
- {
- carbon_menu_item_update_label (carbon_item,
- GTK_WIDGET (object));
- }
- else if (!strcmp (pspec->name, "accel-closure"))
- {
- carbon_menu_item_update_accel_closure (carbon_item,
- GTK_WIDGET (object));
- }
-}
-
-static CarbonMenuItem *
-carbon_menu_item_connect (GtkWidget *menu_item,
- GtkWidget *label,
- MenuRef menu,
- MenuItemIndex index)
-{
- CarbonMenuItem *carbon_item = carbon_menu_item_get (menu_item);
-
- if (!carbon_item)
- {
- carbon_item = carbon_menu_item_new ();
-
- g_object_set_qdata_full (G_OBJECT (menu_item), carbon_menu_item_quark,
- carbon_item,
- (GDestroyNotify) carbon_menu_item_free);
-
- g_signal_connect (menu_item, "notify",
- G_CALLBACK (carbon_menu_item_notify),
- carbon_item);
-
- if (label)
- g_signal_connect_swapped (label, "notify::label",
- G_CALLBACK (carbon_menu_item_notify_label),
- menu_item);
- }
-
- carbon_item->menu = menu;
- carbon_item->index = index;
-
- return carbon_item;
-}
-
-
-/*
- * carbon event handler
- */
-
-static OSStatus
-menu_event_handler_func (EventHandlerCallRef event_handler_call_ref,
- EventRef event_ref,
- void *data)
-{
- UInt32 event_class = GetEventClass (event_ref);
- UInt32 event_kind = GetEventKind (event_ref);
- MenuRef menu_ref;
-
- switch (event_class)
- {
- case kEventClassCommand:
- /* This is called when activating (is that the right GTK+ term?)
- * a menu item.
- */
- if (event_kind == kEventCommandProcess)
- {
- HICommand command;
- OSStatus err;
-
- //g_print ("Menu: kEventClassCommand/kEventCommandProcess\n");
-
- err = GetEventParameter (event_ref, kEventParamDirectObject,
- typeHICommand, 0,
- sizeof (command), 0, &command);
-
- if (err == noErr)
- {
- GtkWidget *widget = NULL;
-
- if (command.commandID == kHICommandQuit)
- {
- gtk_main_quit (); /* Just testing... */
- return noErr;
- }
-
- /* Get any GtkWidget associated with the item. */
- err = GetMenuItemProperty (command.menu.menuRef,
- command.menu.menuItemIndex,
- GTK_QUARTZ_MENU_CREATOR,
- GTK_QUARTZ_ITEM_WIDGET,
- sizeof (widget), 0, &widget);
- if (err == noErr && widget)
- {
- gtk_menu_item_activate (GTK_MENU_ITEM (widget));
- return noErr;
- }
- }
- }
- break;
-
- case kEventClassMenu:
- GetEventParameter (event_ref,
- kEventParamDirectObject,
- typeMenuRef,
- NULL,
- sizeof (menu_ref),
- NULL,
- &menu_ref);
-
- switch (event_kind)
- {
- case kEventMenuTargetItem:
- /* This is called when an item is selected (what is the
- * GTK+ term? prelight?)
- */
- //g_print ("kEventClassMenu/kEventMenuTargetItem\n");
- break;
-
- case kEventMenuOpening:
- /* Is it possible to dynamically build the menu here? We
- * can at least set visibility/sensitivity.
- */
- //g_print ("kEventClassMenu/kEventMenuOpening\n");
- break;
-
- case kEventMenuClosed:
- //g_print ("kEventClassMenu/kEventMenuClosed\n");
- break;
-
- default:
- break;
- }
-
- break;
-
- default:
- break;
- }
-
- return CallNextEventHandler (event_handler_call_ref, event_ref);
-}
-
-static void
-setup_menu_event_handler (void)
-{
- EventHandlerUPP menu_event_handler_upp;
- EventHandlerRef menu_event_handler_ref;
- const EventTypeSpec menu_events[] = {
- { kEventClassCommand, kEventCommandProcess },
- { kEventClassMenu, kEventMenuTargetItem },
- { kEventClassMenu, kEventMenuOpening },
- { kEventClassMenu, kEventMenuClosed }
- };
-
- /* FIXME: We might have to install one per window? */
-
- menu_event_handler_upp = NewEventHandlerUPP (menu_event_handler_func);
- InstallEventHandler (GetApplicationEventTarget (), menu_event_handler_upp,
- GetEventTypeCount (menu_events), menu_events, 0,
- &menu_event_handler_ref);
-
-#if 0
- /* FIXME: Remove the handler with: */
- RemoveEventHandler(menu_event_handler_ref);
- DisposeEventHandlerUPP(menu_event_handler_upp);
-#endif
-}
-
-static void
-sync_menu_shell (GtkMenuShell *menu_shell,
- MenuRef carbon_menu,
- gboolean toplevel)
-{
- GList *children;
- GList *l;
- MenuItemIndex carbon_index = 1;
-
- carbon_menu_connect (GTK_WIDGET (menu_shell), carbon_menu);
-
- children = gtk_container_get_children (GTK_CONTAINER (menu_shell));
-
- for (l = children; l; l = l->next)
- {
- GtkWidget *menu_item = l->data;
- CarbonMenuItem *carbon_item;
-
- if (GTK_IS_TEAROFF_MENU_ITEM (menu_item))
- continue;
-
- if (toplevel && g_object_get_data (G_OBJECT (menu_item), "gtk-empty-menu-item"))
- continue;
-
- carbon_item = carbon_menu_item_get (menu_item);
-
- if (carbon_item && carbon_item->index != carbon_index)
- {
- DeleteMenuItem (carbon_item->menu,
- carbon_item->index);
- carbon_item = NULL;
- }
-
- if (!carbon_item)
- {
- GtkWidget *label = NULL;
- const gchar *label_text;
- CFStringRef cfstr = NULL;
- MenuItemAttributes attributes = 0;
-
- label_text = get_menu_label_text (menu_item, &label);
- if (label_text)
- cfstr = CFStringCreateWithCString (NULL, label_text,
- kCFStringEncodingUTF8);
-
- if (GTK_IS_SEPARATOR_MENU_ITEM (menu_item))
- attributes |= kMenuItemAttrSeparator;
-
- if (!GTK_WIDGET_IS_SENSITIVE (menu_item))
- attributes |= kMenuItemAttrDisabled;
-
- if (!GTK_WIDGET_VISIBLE (menu_item))
- attributes |= kMenuItemAttrHidden;
-
- InsertMenuItemTextWithCFString (carbon_menu, cfstr,
- carbon_index,
- attributes, 0);
- SetMenuItemProperty (carbon_menu, carbon_index,
- GTK_QUARTZ_MENU_CREATOR,
- GTK_QUARTZ_ITEM_WIDGET,
- sizeof (menu_item), &menu_item);
-
- if (cfstr)
- CFRelease (cfstr);
-
- carbon_item = carbon_menu_item_connect (menu_item, label,
- carbon_menu,
- carbon_index);
-
- if (GTK_IS_CHECK_MENU_ITEM (menu_item))
- carbon_menu_item_update_active (carbon_item, menu_item);
-
- carbon_menu_item_update_accel_closure (carbon_item, menu_item);
-
- if (gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu_item)))
- carbon_menu_item_update_submenu (carbon_item, menu_item);
- }
-
- carbon_index++;
- }
-
- g_list_free (children);
-}
-
-void
-sync_menu_takeover_menu (GtkMenuShell *menu_shell)
-{
- MenuRef carbon_menubar;
-
- g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
-
- if (carbon_menu_quark == 0)
- carbon_menu_quark = g_quark_from_static_string ("CarbonMenu");
-
- if (carbon_menu_item_quark == 0)
- carbon_menu_item_quark = g_quark_from_static_string ("CarbonMenuItem");
-
- CreateNewMenu (0 /*id*/, 0 /*options*/, &carbon_menubar);
- SetRootMenu (carbon_menubar);
-
- setup_menu_event_handler ();
-
- sync_menu_shell (menu_shell, carbon_menubar, TRUE);
-}
-
-#else
-
-void
-sync_menu_takeover_menu (GtkMenuShell *menu_shell)
-{
-
-}
-
-#endif
diff --git a/src/audacious/sync-menu.h b/src/audacious/sync-menu.h
deleted file mode 100644
index 0715a31..0000000
--- a/src/audacious/sync-menu.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* GTK+ Integration for the Mac OS X Menubar.
- *
- * Copyright (C) 2007 Pioneer Research Center USA, Inc.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-void sync_menu_takeover_menu (GtkMenuShell *menu_shell);
-
-G_END_DECLS
diff --git a/src/audacious/ui_albumart.c b/src/audacious/ui_albumart.c
index 4bc38be..940ceed 100644
--- a/src/audacious/ui_albumart.c
+++ b/src/audacious/ui_albumart.c
@@ -28,9 +28,7 @@
#include <gtk/gtk.h>
#include <string.h>
-#include "ui_fileinfopopup.h"
-#include "main.h"
-#include "playback.h"
+#include "audconfig.h"
static gboolean
has_front_cover_extension(const gchar *name)
@@ -117,9 +115,8 @@ is_file_image(const gchar *imgfile, const gchar *file_name)
}
}
-gchar*
-fileinfo_recursive_get_image(const gchar* path,
- const gchar* file_name, gint depth)
+static gchar * fileinfo_recursive_get_image (const gchar * path, const gchar *
+ file_name, gint depth)
{
GDir *d;
@@ -191,3 +188,14 @@ fileinfo_recursive_get_image(const gchar* path,
return NULL;
}
+
+gchar * get_associated_image_file (const gchar * filename)
+{
+ gchar * path = g_path_get_dirname (filename);
+ gchar * base = g_path_get_basename (filename);
+ gchar * image_file = fileinfo_recursive_get_image (path, base, 0);
+
+ g_free (path);
+ g_free (base);
+ return image_file;
+}
diff --git a/src/audacious/ui_albumart.h b/src/audacious/ui_albumart.h
new file mode 100644
index 0000000..8775128
--- /dev/null
+++ b/src/audacious/ui_albumart.h
@@ -0,0 +1,8 @@
+/*
+ * TEMPORARY.
+ *
+ * Album art needs to be reworked. It should be read from file tags and stored
+ * in tuples. -jlindgren
+ */
+
+gchar * get_associated_image_file (const gchar * filename);
diff --git a/src/audacious/ui_fileinfo.c b/src/audacious/ui_fileinfo.c
deleted file mode 100644
index 7c256ad..0000000
--- a/src/audacious/ui_fileinfo.c
+++ /dev/null
@@ -1,993 +0,0 @@
-/*
- * Audacious: A cross-platform multimedia player
- * Copyright (c) 2006 William Pitcock, Tony Vroon, George Averill,
- * Giacomo Lozito, Derek Pomery and Yoshiki Yazawa.
- * Copyright (c) 2008 Eugene Zagidullin
- *
- * 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; under version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses>.
- *
- * The Audacious team does not consider modular code linking to
- * Audacious or using our public API to be a derived work.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <gdk/gdkkeysyms.h>
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <gtk/gtk.h>
-#include <string.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <sys/types.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "plugin.h"
-#include "pluginenum.h"
-#include "effect.h"
-#include "audstrings.h"
-#include "general.h"
-#include "output.h"
-#include "playlist-new.h"
-#include "probe.h"
-#include "visualization.h"
-
-#include "main.h"
-#include "util.h"
-#include "tuple.h"
-#include "vfs.h"
-
-#include "build_stamp.h"
-#include "ui_fileinfo.h"
-
-#define G_FREE_CLEAR(a) if(a != NULL) { g_free(a); a = NULL; }
-#define STATUS_TIMEOUT 3*1000
-
-GtkWidget *fileinfo_win = NULL;
-
-GtkWidget *entry_location;
-GtkWidget *entry_title;
-GtkWidget *entry_artist;
-GtkWidget *entry_album;
-GtkWidget *entry_comment;
-GtkWidget *entry_year;
-GtkWidget *entry_track;
-GtkWidget *entry_genre;
-
-GtkWidget *image_artwork;
-
-GtkWidget *image_fileicon;
-GtkWidget *label_format_name;
-GtkWidget *label_quality;
-GtkWidget *label_bitrate;
-GtkWidget *btn_apply;
-GtkWidget *label_mini_status;
-GtkWidget *arrow_rawdata;
-GtkWidget *treeview_rawdata;
-
-enum {
- RAWDATA_KEY,
- RAWDATA_VALUE,
- RAWDATA_N_COLS
-};
-
-static gchar *current_file = NULL;
-static InputPlugin *current_ip = NULL;
-static gboolean something_changed = FALSE;
-
-/* stolen from Audacious 1.4 vorbis plugin. --nenolod */
-static const gchar *genre_table[] = {
- N_("Blues"), N_("Classic Rock"), N_("Country"), N_("Dance"),
- N_("Disco"), N_("Funk"), N_("Grunge"), N_("Hip-Hop"),
- N_("Jazz"), N_("Metal"), N_("New Age"), N_("Oldies"),
- N_("Other"), N_("Pop"), N_("R&B"), N_("Rap"), N_("Reggae"),
- N_("Rock"), N_("Techno"), N_("Industrial"), N_("Alternative"),
- N_("Ska"), N_("Death Metal"), N_("Pranks"), N_("Soundtrack"),
- N_("Euro-Techno"), N_("Ambient"), N_("Trip-Hop"), N_("Vocal"),
- N_("Jazz+Funk"), N_("Fusion"), N_("Trance"), N_("Classical"),
- N_("Instrumental"), N_("Acid"), N_("House"), N_("Game"),
- N_("Sound Clip"), N_("Gospel"), N_("Noise"), N_("AlternRock"),
- N_("Bass"), N_("Soul"), N_("Punk"), N_("Space"),
- N_("Meditative"), N_("Instrumental Pop"),
- N_("Instrumental Rock"), N_("Ethnic"), N_("Gothic"),
- N_("Darkwave"), N_("Techno-Industrial"), N_("Electronic"),
- N_("Pop-Folk"), N_("Eurodance"), N_("Dream"),
- N_("Southern Rock"), N_("Comedy"), N_("Cult"),
- N_("Gangsta Rap"), N_("Top 40"), N_("Christian Rap"),
- N_("Pop/Funk"), N_("Jungle"), N_("Native American"),
- N_("Cabaret"), N_("New Wave"), N_("Psychedelic"), N_("Rave"),
- N_("Showtunes"), N_("Trailer"), N_("Lo-Fi"), N_("Tribal"),
- N_("Acid Punk"), N_("Acid Jazz"), N_("Polka"), N_("Retro"),
- N_("Musical"), N_("Rock & Roll"), N_("Hard Rock"), N_("Folk"),
- N_("Folk/Rock"), N_("National Folk"), N_("Swing"),
- N_("Fast-Fusion"), N_("Bebob"), N_("Latin"), N_("Revival"),
- N_("Celtic"), N_("Bluegrass"), N_("Avantgarde"),
- N_("Gothic Rock"), N_("Progressive Rock"),
- N_("Psychedelic Rock"), N_("Symphonic Rock"), N_("Slow Rock"),
- N_("Big Band"), N_("Chorus"), N_("Easy Listening"),
- N_("Acoustic"), N_("Humour"), N_("Speech"), N_("Chanson"),
- N_("Opera"), N_("Chamber Music"), N_("Sonata"), N_("Symphony"),
- N_("Booty Bass"), N_("Primus"), N_("Porn Groove"),
- N_("Satire"), N_("Slow Jam"), N_("Club"), N_("Tango"),
- N_("Samba"), N_("Folklore"), N_("Ballad"), N_("Power Ballad"),
- N_("Rhythmic Soul"), N_("Freestyle"), N_("Duet"),
- N_("Punk Rock"), N_("Drum Solo"), N_("A Cappella"),
- N_("Euro-House"), N_("Dance Hall"), N_("Goa"),
- N_("Drum & Bass"), N_("Club-House"), N_("Hardcore"),
- N_("Terror"), N_("Indie"), N_("BritPop"), N_("Negerpunk"),
- N_("Polsk Punk"), N_("Beat"), N_("Christian Gangsta Rap"),
- N_("Heavy Metal"), N_("Black Metal"), N_("Crossover"),
- N_("Contemporary Christian"), N_("Christian Rock"),
- N_("Merengue"), N_("Salsa"), N_("Thrash Metal"),
- N_("Anime"), N_("JPop"), N_("Synthpop")
-};
-
-static GList *genre_list = NULL;
-
-static void
-fileinfo_entry_set_text(GtkWidget *widget, const char *text)
-{
- if (widget == NULL)
- return;
-
- gtk_entry_set_text(GTK_ENTRY(widget), text != NULL ? text : "");
-}
-
-static void
-set_entry_str_from_field(GtkWidget *widget, Tuple *tuple, gint fieldn, gboolean editable)
-{
- gchar *text;
-
- if(widget != NULL) {
- text = (gchar*)tuple_get_string(tuple, fieldn, NULL);
- gtk_entry_set_text(GTK_ENTRY(widget), text != NULL ? text : "");
- gtk_editable_set_editable(GTK_EDITABLE(widget), editable);
- }
-}
-
-static void
-set_entry_int_from_field(GtkWidget *widget, Tuple *tuple, gint fieldn, gboolean editable)
-{
- gchar *text;
-
- if(widget == NULL) return;
-
- if(tuple_get_value_type(tuple, fieldn, NULL) == TUPLE_INT) {
- text = g_strdup_printf("%d", tuple_get_int(tuple, fieldn, NULL));
- gtk_entry_set_text(GTK_ENTRY(widget), text);
- gtk_editable_set_editable(GTK_EDITABLE(widget), editable);
- g_free(text);
- } else {
- gtk_entry_set_text(GTK_ENTRY(widget), "");
- gtk_editable_set_editable(GTK_EDITABLE(widget), editable);
- }
-}
-
-static void
-set_field_str_from_entry(Tuple *tuple, gint fieldn, GtkWidget *widget)
-{
- if(widget == NULL) return;
- tuple_associate_string(tuple, fieldn, NULL, gtk_entry_get_text(GTK_ENTRY(widget)));
-}
-
-static void
-set_field_int_from_entry(Tuple *tuple, gint fieldn, GtkWidget *widget)
-{
- gchar *tmp;
- if(widget == NULL) return;
-
- tmp = (gchar*)gtk_entry_get_text(GTK_ENTRY(widget));
- if(*tmp != '\0')
- tuple_associate_int(tuple, fieldn, NULL, atoi(tmp));
- else
- tuple_associate_int(tuple, fieldn, NULL, -1);
-}
-
-static void
-fileinfo_label_set_text(GtkWidget *widget, const char *text)
-{
- gchar *tmp;
-
- if (widget == NULL)
- return;
-
- if (text) {
- tmp = g_strdup_printf("<span size=\"small\">%s</span>", text);
- gtk_label_set_text(GTK_LABEL(widget), tmp);
- gtk_label_set_use_markup(GTK_LABEL(widget), TRUE);
- g_free(tmp);
- } else {
- gtk_label_set_text(GTK_LABEL(widget), _("<span size=\"small\">n/a</span>"));
- gtk_label_set_use_markup(GTK_LABEL(widget), TRUE);
- }
-}
-
-static void
-fileinfo_entry_set_image(GtkWidget *widget, const char *text)
-{
- GdkPixbuf *pixbuf;
- int width, height;
- double aspect;
- GdkPixbuf *pixbuf2;
-
- if (widget == NULL)
- return;
-
- pixbuf = gdk_pixbuf_new_from_file(text, NULL);
-
- if (pixbuf == NULL)
- return;
-
- width = gdk_pixbuf_get_width(GDK_PIXBUF(pixbuf));
- height = gdk_pixbuf_get_height(GDK_PIXBUF(pixbuf));
-
- if (strcmp(DATA_DIR "/images/audio.png", text)) {
- if (width == 0)
- width = 1;
- aspect = (double)height / (double)width;
-
- if (aspect > 1.0) {
- height = (int)(cfg.filepopup_pixelsize * aspect);
- width = cfg.filepopup_pixelsize;
- } else {
- height = cfg.filepopup_pixelsize;
- width = (int)(cfg.filepopup_pixelsize / aspect);
- }
-
- pixbuf2 = gdk_pixbuf_scale_simple(GDK_PIXBUF(pixbuf), width, height, GDK_INTERP_BILINEAR);
- g_object_unref(G_OBJECT(pixbuf));
- pixbuf = pixbuf2;
- }
-
- gtk_image_set_from_pixbuf(GTK_IMAGE(widget), GDK_PIXBUF(pixbuf));
- g_object_unref(G_OBJECT(pixbuf));
-}
-
-static int
-fileinfo_hide(gpointer unused)
-{
- if(GTK_WIDGET_VISIBLE(fileinfo_win)) gtk_widget_hide(fileinfo_win);
-
- /* Clear it out. */
- fileinfo_entry_set_text(entry_title, "");
- fileinfo_entry_set_text(entry_artist, "");
- fileinfo_entry_set_text(entry_album, "");
- fileinfo_entry_set_text(entry_comment, "");
- fileinfo_entry_set_text(gtk_bin_get_child(GTK_BIN(entry_genre)), "");
- fileinfo_entry_set_text(entry_year, "");
- fileinfo_entry_set_text(entry_track, "");
- fileinfo_entry_set_text(entry_location, "");
-
- fileinfo_label_set_text(label_format_name, NULL);
- fileinfo_label_set_text(label_quality, NULL);
- fileinfo_label_set_text(label_bitrate, NULL);
-
- if (label_mini_status != NULL) {
- gtk_label_set_text(GTK_LABEL(label_mini_status), "<span size=\"small\"></span>");
- gtk_label_set_use_markup(GTK_LABEL(label_mini_status), TRUE);
- }
-
- something_changed = FALSE;
- gtk_widget_set_sensitive(btn_apply, FALSE);
-
- current_ip = NULL;
- G_FREE_CLEAR(current_file);
-
- fileinfo_entry_set_image(image_artwork, DATA_DIR "/images/audio.png");
- return 1;
-}
-
-static void
-entry_changed (GtkEditable *editable, gpointer user_data)
-{
- if(current_file != NULL && current_ip != NULL && current_ip->update_song_tuple != NULL) {
- something_changed = TRUE;
- gtk_widget_set_sensitive(btn_apply, TRUE);
- }
-}
-
-static gboolean
-ministatus_timeout_proc (gpointer data)
-{
- GtkLabel *status = GTK_LABEL(data);
- gtk_label_set_text(status, "<span size=\"small\"></span>");
- gtk_label_set_use_markup(status, TRUE);
-
- return FALSE;
-}
-
-static void
-ministatus_display_message(gchar *text)
-{
- if(label_mini_status != NULL) {
- gchar *tmp = g_strdup_printf("<span size=\"small\">%s</span>", text);
- gtk_label_set_text(GTK_LABEL(label_mini_status), tmp);
- g_free(tmp);
- gtk_label_set_use_markup(GTK_LABEL(label_mini_status), TRUE);
- g_timeout_add (STATUS_TIMEOUT, (GSourceFunc) ministatus_timeout_proc, (gpointer) label_mini_status);
- }
-}
-
-static void
-message_update_successfull()
-{
- ministatus_display_message(_("Metadata updated successfully"));
-}
-
-static void
-message_update_failed()
-{
- ministatus_display_message(_("Metadata updating failed"));
-}
-
-static void
-fileinfo_update_tuple(gpointer data)
-{
- Tuple *tuple;
- VFSFile *fd;
-
- if (current_file != NULL && current_ip != NULL && current_ip->update_song_tuple != NULL && something_changed) {
- tuple = tuple_new();
- fd = vfs_fopen(current_file, "r+b");
-
- if (fd != NULL) {
- set_field_str_from_entry(tuple, FIELD_TITLE, entry_title);
- set_field_str_from_entry(tuple, FIELD_ARTIST, entry_artist);
- set_field_str_from_entry(tuple, FIELD_ALBUM, entry_album);
- set_field_str_from_entry(tuple, FIELD_COMMENT, entry_comment);
- set_field_str_from_entry(tuple, FIELD_GENRE, gtk_bin_get_child(GTK_BIN(entry_genre)));
-
- set_field_int_from_entry(tuple, FIELD_YEAR, entry_year);
- set_field_int_from_entry(tuple, FIELD_TRACK_NUMBER, entry_track);
-
- plugin_set_current((Plugin *)current_ip);
- if (current_ip->update_song_tuple(tuple, fd)) {
- message_update_successfull();
- something_changed = FALSE;
- gtk_widget_set_sensitive(btn_apply, FALSE);
- } else
- message_update_failed();
-
- vfs_fclose(fd);
-
- } else
- message_update_failed();
-
- mowgli_object_unref(tuple);
- }
-}
-
-/**
- * Looks up an icon from a NULL-terminated list of icon names.
- *
- * size: the requested size
- * name: the default name
- * ... : a NULL-terminated list of alternates
- */
-GdkPixbuf *
-themed_icon_lookup(gint size, const gchar *name, ...)
-{
- GtkIconTheme *icon_theme;
- GdkPixbuf *pixbuf;
- GError *error = NULL;
- gchar *n;
- va_list par;
-
- icon_theme = gtk_icon_theme_get_default ();
- pixbuf = gtk_icon_theme_load_icon (icon_theme, name, size, 0, &error);
-
- if (pixbuf != NULL)
- return pixbuf;
-
- if (error != NULL)
- g_error_free(error);
-
- /* fallback */
- va_start(par, name);
- while((n = (gchar*)va_arg(par, gchar *)) != NULL) {
- error = NULL;
- pixbuf = gtk_icon_theme_load_icon (icon_theme, n, size, 0, &error);
-
- if (pixbuf) {
- va_end(par);
- return pixbuf;
- }
-
- if (error != NULL)
- g_error_free(error);
- }
-
- return NULL;
-}
-
-/**
- * Intelligently looks up an icon for a mimetype. Supports
- * HIDEOUSLY BROKEN gnome icon naming scheme too.
- *
- * size : the requested size
- * mime_type: the mime type.
- */
-GdkPixbuf *
-mime_icon_lookup(gint size, const gchar *mime_type) /* smart icon resolving routine :) */
-{
- gchar *mime_as_is; /* audio-x-mp3 */
- gchar *mime_gnome; /* gnome-mime-audio-x-mp3 */
- gchar *mime_generic; /* audio-x-generic */
- gchar *mime_gnome_generic; /* gnome-mime-audio */
-
- GdkPixbuf *icon = NULL;
-
- gchar **s = g_strsplit(mime_type, "/", 2);
- if(s[1] != NULL) {
- mime_as_is = g_strdup_printf("%s-%s", s[0], s[1]);
- mime_gnome = g_strdup_printf("gnome-mime-%s-%s", s[0], s[1]);
- mime_generic = g_strdup_printf("%s-x-generic", s[0]);
- mime_gnome_generic = g_strdup_printf("gnome-mime-%s", s[0]);
- icon = themed_icon_lookup(size, mime_as_is, mime_gnome, mime_generic, mime_gnome_generic, s[0], NULL); /* s[0] is category */
- g_free(mime_gnome_generic);
- g_free(mime_generic);
- g_free(mime_gnome);
- g_free(mime_as_is);
- }
- g_strfreev(s);
-
- return icon;
-}
-
-static gboolean fileinfo_keypress (GtkWidget * widget, GdkEventKey * event,
- void * unused)
-{
- if (event->keyval == GDK_Escape)
- {
- fileinfo_hide (NULL);
- return TRUE;
- }
-
- return FALSE;
-}
-
-void
-create_fileinfo_window(void)
-{
- GtkWidget *hbox;
- GtkWidget *hbox_status_and_bbox;
- GtkWidget *vbox0;
- GtkWidget *vbox1;
- GtkWidget *vbox2;
- GtkWidget *vbox3;
- GtkWidget *label_title;
- GtkWidget *label_artist;
- GtkWidget *label_album;
- GtkWidget *label_comment;
- GtkWidget *label_genre;
- GtkWidget *label_year;
- GtkWidget *label_track;
- GtkWidget *label_location;
- GtkWidget *label_general;
- GtkWidget *label_format;
- GtkWidget *label_quality_label;
- GtkWidget *label_bitrate_label;
- GtkWidget *codec_hbox;
- GtkWidget *codec_table;
- GtkWidget *table1;
- GtkWidget *bbox_close;
- GtkWidget *btn_close;
- GtkWidget *alignment;
- GtkWidget *separator;
- GtkWidget *scrolledwindow;
- GtkTreeViewColumn *column;
- GtkCellRenderer *renderer;
- gint i;
-
- fileinfo_win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_container_set_border_width(GTK_CONTAINER(fileinfo_win), 6);
- gtk_window_set_title(GTK_WINDOW(fileinfo_win), _("Track Information"));
- gtk_window_set_position(GTK_WINDOW(fileinfo_win), GTK_WIN_POS_CENTER);
- gtk_window_set_type_hint(GTK_WINDOW(fileinfo_win), GDK_WINDOW_TYPE_HINT_DIALOG);
-
- vbox0 = gtk_vbox_new(FALSE, 0);
- gtk_container_add(GTK_CONTAINER(fileinfo_win), vbox0);
-
- hbox = gtk_hbox_new(FALSE, 6);
- gtk_box_pack_start(GTK_BOX(vbox0), hbox, TRUE, TRUE, 0);
-
- image_artwork = gtk_image_new();
- gtk_box_pack_start(GTK_BOX(hbox), image_artwork, FALSE, FALSE, 0);
- gtk_misc_set_alignment(GTK_MISC(image_artwork), 0.5, 0);
- gtk_image_set_from_file(GTK_IMAGE(image_artwork), DATA_DIR "/images/audio.png");
- separator = gtk_vseparator_new();
- gtk_box_pack_start(GTK_BOX(hbox), separator, FALSE, FALSE, 0);
-
- vbox1 = gtk_vbox_new(FALSE, 0);
- gtk_box_pack_start(GTK_BOX(hbox), vbox1, TRUE, TRUE, 0);
-
- alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
- gtk_box_pack_start(GTK_BOX(vbox1), alignment, TRUE, TRUE, 0);
-
- vbox2 = gtk_vbox_new(FALSE, 0);
- gtk_container_add(GTK_CONTAINER(alignment), vbox2);
-
- alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
- gtk_box_pack_start(GTK_BOX(vbox1), alignment, TRUE, TRUE, 0);
-
- vbox3 = gtk_vbox_new(FALSE, 0);
- gtk_container_add(GTK_CONTAINER(alignment), vbox3);
-
- label_general = gtk_label_new(_("<span size=\"small\">General</span>"));
- gtk_box_pack_start (GTK_BOX (vbox2), label_general, FALSE, FALSE, 0);
- gtk_label_set_use_markup(GTK_LABEL(label_general), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_general), 0, 0.5);
-
- alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
- gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 6, 0, 0);
- gtk_box_pack_start (GTK_BOX (vbox2), alignment, FALSE, FALSE, 0);
-
- codec_hbox = gtk_hbox_new(FALSE, 6);
- gtk_container_add (GTK_CONTAINER(alignment), codec_hbox);
-
- image_fileicon = gtk_image_new_from_stock (GTK_STOCK_MISSING_IMAGE, GTK_ICON_SIZE_DIALOG);
- gtk_box_pack_start (GTK_BOX (codec_hbox), image_fileicon, FALSE, FALSE, 0);
-
- codec_table = gtk_table_new(3, 2, FALSE);
- gtk_table_set_row_spacings (GTK_TABLE(codec_table), 6);
- gtk_table_set_col_spacings (GTK_TABLE(codec_table), 12);
- gtk_box_pack_start (GTK_BOX (codec_hbox), codec_table, FALSE, FALSE, 0);
-
- label_format = gtk_label_new(_("<span size=\"small\">Format:</span>"));
- gtk_label_set_use_markup(GTK_LABEL(label_format), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_format), 0, 0.5);
- label_quality_label = gtk_label_new(_("<span size=\"small\">Quality:</span>"));
- gtk_label_set_use_markup(GTK_LABEL(label_quality_label), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_quality_label), 0, 0.5);
- label_bitrate_label = gtk_label_new(_("<span size=\"small\">Bitrate:</span>"));
- gtk_label_set_use_markup(GTK_LABEL(label_bitrate_label), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_bitrate_label), 0, 0.5);
-
- label_format_name = gtk_label_new(_("<span size=\"small\">n/a</span>"));
- gtk_label_set_use_markup(GTK_LABEL(label_format_name), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_format_name), 0, 0.5);
- label_quality = gtk_label_new(_("<span size=\"small\">n/a</span>"));
- gtk_label_set_use_markup(GTK_LABEL(label_quality), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_quality), 0, 0.5);
- label_bitrate = gtk_label_new(_("<span size=\"small\">n/a</span>"));
- gtk_label_set_use_markup(GTK_LABEL(label_bitrate), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_bitrate), 0, 0.5);
-
- gtk_table_attach(GTK_TABLE(codec_table), label_format, 0, 1, 0, 1,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- gtk_table_attach(GTK_TABLE(codec_table), label_format_name, 1, 2, 0, 1,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- gtk_table_attach(GTK_TABLE(codec_table), label_quality_label, 0, 1, 1, 2,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- gtk_table_attach(GTK_TABLE(codec_table), label_quality, 1, 2, 1, 2,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- gtk_table_attach(GTK_TABLE(codec_table), label_bitrate_label, 0, 1, 2, 3,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- gtk_table_attach(GTK_TABLE(codec_table), label_bitrate, 1, 2, 2, 3,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
-
- label_title = gtk_label_new(_("<span size=\"small\">Title</span>"));
- gtk_box_pack_start(GTK_BOX(vbox2), label_title, FALSE, FALSE, 0);
- gtk_label_set_use_markup(GTK_LABEL(label_title), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_title), 0, 0);
-
- alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
- gtk_box_pack_start(GTK_BOX(vbox2), alignment, FALSE, FALSE, 0);
- gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 6, 0, 0);
- entry_title = gtk_entry_new();
- gtk_container_add(GTK_CONTAINER(alignment), entry_title);
- g_signal_connect(G_OBJECT(entry_title), "changed", (GCallback) entry_changed, NULL);
-
- label_artist = gtk_label_new(_("<span size=\"small\">Artist</span>"));
- gtk_box_pack_start(GTK_BOX(vbox2), label_artist, FALSE, FALSE, 0);
- gtk_label_set_use_markup(GTK_LABEL(label_artist), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_artist), 0, 0.5);
-
- alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
- gtk_box_pack_start(GTK_BOX(vbox2), alignment, FALSE, FALSE, 0);
- gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 6, 0, 0);
- entry_artist = gtk_entry_new();
- gtk_container_add(GTK_CONTAINER(alignment), entry_artist);
- g_signal_connect(G_OBJECT(entry_artist), "changed", (GCallback) entry_changed, NULL);
-
- label_album = gtk_label_new(_("<span size=\"small\">Album</span>"));
- gtk_box_pack_start(GTK_BOX(vbox2), label_album, FALSE, FALSE, 0);
- gtk_label_set_use_markup(GTK_LABEL(label_album), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_album), 0, 0.5);
-
- alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
- gtk_box_pack_start(GTK_BOX(vbox2), alignment, FALSE, FALSE, 0);
- gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 6, 0, 0);
- entry_album = gtk_entry_new();
- gtk_container_add(GTK_CONTAINER(alignment), entry_album);
- g_signal_connect(G_OBJECT(entry_album), "changed", (GCallback) entry_changed, NULL);
-
- label_comment = gtk_label_new(_("<span size=\"small\">Comment</span>"));
- gtk_box_pack_start(GTK_BOX(vbox2), label_comment, FALSE, FALSE, 0);
- gtk_label_set_use_markup(GTK_LABEL(label_comment), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_comment), 0, 0.5);
-
- alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
- gtk_box_pack_start(GTK_BOX(vbox2), alignment, FALSE, FALSE, 0);
- gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 6, 0, 0);
- entry_comment = gtk_entry_new();
- gtk_container_add (GTK_CONTAINER(alignment), entry_comment);
- g_signal_connect(G_OBJECT(entry_comment), "changed", (GCallback) entry_changed, NULL);
-
- label_genre = gtk_label_new(_("<span size=\"small\">Genre</span>"));
- gtk_box_pack_start(GTK_BOX(vbox2), label_genre, FALSE, FALSE, 0);
- gtk_label_set_use_markup(GTK_LABEL(label_genre), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_genre), 0, 0.5);
-
- alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
- gtk_box_pack_start(GTK_BOX(vbox2), alignment, FALSE, FALSE, 0);
- gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 6, 0, 0);
- entry_genre = gtk_combo_box_entry_new_text();
-
- if (!genre_list) {
- GList *iter;
-
- for (i = 0; i < G_N_ELEMENTS(genre_table); i++)
- genre_list = g_list_prepend(genre_list, _(genre_table[i]));
- genre_list = g_list_sort(genre_list, (GCompareFunc) g_utf8_collate);
-
- MOWGLI_ITER_FOREACH(iter, genre_list)
- gtk_combo_box_append_text(GTK_COMBO_BOX(entry_genre), iter->data);
- }
-
- gtk_container_add(GTK_CONTAINER(alignment), entry_genre);
- g_signal_connect(G_OBJECT(entry_genre), "changed", (GCallback) entry_changed, NULL);
-
- alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
- gtk_box_pack_start(GTK_BOX(vbox2), alignment, FALSE, FALSE, 0);
- gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 6, 0, 0);
- table1 = gtk_table_new(2, 2, FALSE);
- gtk_container_add(GTK_CONTAINER(alignment), table1);
- gtk_table_set_col_spacings(GTK_TABLE(table1), 6);
-
- label_year = gtk_label_new(_("<span size=\"small\">Year</span>"));
- gtk_table_attach(GTK_TABLE(table1), label_year, 0, 1, 0, 1,
- (GtkAttachOptions) (GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- gtk_label_set_use_markup(GTK_LABEL(label_year), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_year), 0, 0.5);
-
- entry_year = gtk_entry_new();
- gtk_table_attach(GTK_TABLE(table1), entry_year, 0, 1, 1, 2,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- g_signal_connect(G_OBJECT(entry_year), "changed", (GCallback) entry_changed, NULL);
-
- label_track = gtk_label_new(_("<span size=\"small\">Track Number</span>"));
- gtk_table_attach(GTK_TABLE(table1), label_track, 1, 2, 0, 1,
- (GtkAttachOptions) (GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- gtk_label_set_use_markup(GTK_LABEL(label_track), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_track), 0, 0.5);
-
- entry_track = gtk_entry_new();
- gtk_table_attach(GTK_TABLE(table1), entry_track, 1, 2, 1, 2,
- (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
- (GtkAttachOptions) (0), 0, 0);
- g_signal_connect(G_OBJECT(entry_track), "changed", (GCallback) entry_changed, NULL);
-
- label_location = gtk_label_new(_("<span size=\"small\">Location</span>"));
- gtk_box_pack_start(GTK_BOX(vbox2), label_location, FALSE, FALSE, 0);
- gtk_label_set_use_markup(GTK_LABEL(label_location), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_location), 0, 0.5);
-
- alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
- gtk_box_pack_start (GTK_BOX (vbox2), alignment, FALSE, FALSE, 0);
- gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 6, 0, 0);
-
- entry_location = gtk_entry_new();
- gtk_container_add(GTK_CONTAINER(alignment), entry_location);
- gtk_editable_set_editable(GTK_EDITABLE(entry_location), FALSE);
-
- alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
- hbox = gtk_hbox_new(FALSE, 0);
- gtk_container_add(GTK_CONTAINER(alignment), hbox);
- gtk_box_pack_start(GTK_BOX(vbox3), alignment, TRUE, TRUE, 0);
-
- alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
- gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 6, 0, 0);
- arrow_rawdata = gtk_expander_new(_("<span size=\"small\">Raw Metadata</span>"));
- gtk_expander_set_use_markup(GTK_EXPANDER(arrow_rawdata), TRUE);
- gtk_container_add(GTK_CONTAINER(alignment), arrow_rawdata);
- gtk_box_pack_start(GTK_BOX(hbox), alignment, TRUE, TRUE, 0);
-
- scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
- gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
- gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow), GTK_SHADOW_IN);
- gtk_container_add(GTK_CONTAINER(arrow_rawdata), scrolledwindow);
-
- treeview_rawdata = gtk_tree_view_new();
- gtk_container_add(GTK_CONTAINER(scrolledwindow), treeview_rawdata);
- gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview_rawdata), TRUE);
- gtk_tree_view_set_reorderable(GTK_TREE_VIEW(treeview_rawdata), TRUE);
- gtk_widget_set_size_request(treeview_rawdata, -1, 130);
-
- column = gtk_tree_view_column_new();
- gtk_tree_view_column_set_title(column, _("Key"));
- gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
- gtk_tree_view_column_set_spacing(column, 4);
- gtk_tree_view_column_set_resizable(column, FALSE);
- gtk_tree_view_column_set_fixed_width(column, 50);
-
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(column, renderer, FALSE);
- gtk_tree_view_column_set_attributes(column, renderer,
- "text", RAWDATA_KEY, NULL);
- gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_rawdata), column);
-
- column = gtk_tree_view_column_new();
- gtk_tree_view_column_set_title(column, _("Value"));
- gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
- gtk_tree_view_column_set_spacing(column, 4);
- gtk_tree_view_column_set_resizable(column, FALSE);
- gtk_tree_view_column_set_fixed_width(column, 50);
-
- renderer = gtk_cell_renderer_text_new();
- gtk_tree_view_column_pack_start(column, renderer, FALSE);
- gtk_tree_view_column_set_attributes(column, renderer,
- "text", RAWDATA_VALUE, NULL);
- gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_rawdata), column);
-
- hbox_status_and_bbox = gtk_hbox_new(FALSE, 0);
- gtk_box_pack_start (GTK_BOX (vbox0), hbox_status_and_bbox, FALSE, FALSE, 0);
-
- label_mini_status = gtk_label_new("<span size=\"small\"></span>");
- gtk_label_set_use_markup(GTK_LABEL(label_mini_status), TRUE);
- gtk_misc_set_alignment(GTK_MISC(label_mini_status), 0, 0.5);
- gtk_box_pack_start (GTK_BOX (hbox_status_and_bbox), label_mini_status, TRUE, TRUE, 0);
-
- bbox_close = gtk_hbutton_box_new();
- gtk_box_set_spacing(GTK_BOX(bbox_close), 6);
- gtk_box_pack_start(GTK_BOX(hbox_status_and_bbox), bbox_close, FALSE, FALSE, 0);
- gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox_close), GTK_BUTTONBOX_END);
-
- btn_apply = gtk_button_new_from_stock("gtk-save");
- gtk_container_add(GTK_CONTAINER(bbox_close), btn_apply);
- g_signal_connect(G_OBJECT(btn_apply), "clicked", (GCallback) fileinfo_update_tuple, NULL);
- gtk_widget_set_sensitive(btn_apply, FALSE);
-
- btn_close = gtk_button_new_from_stock("gtk-close");
- gtk_container_add(GTK_CONTAINER(bbox_close), btn_close);
- GTK_WIDGET_SET_FLAGS(btn_close, GTK_CAN_DEFAULT);
- g_signal_connect(G_OBJECT(btn_close), "clicked", (GCallback) fileinfo_hide, NULL);
- g_signal_connect ((GObject *) fileinfo_win, "delete-event", (GCallback)
- fileinfo_hide, NULL);
- g_signal_connect ((GObject *) fileinfo_win, "key-press-event", (GCallback)
- fileinfo_keypress, NULL);
-
- gtk_widget_show_all (vbox0);
-}
-
-static void
-fileinfo_show_for_tuple(Tuple *tuple, gboolean updating_enabled)
-{
- gchar *tmp = NULL;
- GdkPixbuf *icon = NULL;
- GtkTreeIter iter;
- GtkListStore *store;
- mowgli_dictionary_iteration_state_t state;
- TupleValue *tvalue;
- gint i;
-
- if (tuple == NULL)
- return;
-
- if(!updating_enabled) {
- current_ip = NULL;
- G_FREE_CLEAR(current_file);
- }
-
- something_changed = FALSE;
-
- if (fileinfo_win == NULL)
- create_fileinfo_window();
-
- if (!GTK_WIDGET_REALIZED(fileinfo_win))
- gtk_widget_realize(fileinfo_win);
-
- set_entry_str_from_field(entry_title, tuple, FIELD_TITLE, updating_enabled);
- set_entry_str_from_field(entry_artist, tuple, FIELD_ARTIST, updating_enabled);
- set_entry_str_from_field(entry_album, tuple, FIELD_ALBUM, updating_enabled);
- set_entry_str_from_field(entry_comment, tuple, FIELD_COMMENT, updating_enabled);
- set_entry_str_from_field(gtk_bin_get_child(GTK_BIN(entry_genre)), tuple, FIELD_GENRE, updating_enabled);
-
- tmp = g_strdup_printf ("%s%s",
- tuple_get_string(tuple, FIELD_FILE_PATH, NULL),
- tuple_get_string(tuple, FIELD_FILE_NAME, NULL));
-
- if (tmp) {
- fileinfo_entry_set_text(entry_location, tmp);
- g_free(tmp);
- }
-
- /* set empty string if field not availaible. --eugene */
- set_entry_int_from_field(entry_year, tuple, FIELD_YEAR, updating_enabled);
- set_entry_int_from_field(entry_track, tuple, FIELD_TRACK_NUMBER, updating_enabled);
-
- fileinfo_label_set_text(label_format_name, tuple_get_string(tuple, FIELD_CODEC, NULL));
- fileinfo_label_set_text(label_quality, tuple_get_string(tuple, FIELD_QUALITY, NULL));
-
- if (tuple_get_value_type(tuple, FIELD_BITRATE, NULL) == TUPLE_INT) {
- tmp = g_strdup_printf(_("%d kb/s"), tuple_get_int(tuple, FIELD_BITRATE, NULL));
- fileinfo_label_set_text(label_bitrate, tmp);
- g_free(tmp);
- } else
- fileinfo_label_set_text(label_bitrate, NULL);
-
- tmp = (gchar *)tuple_get_string(tuple, FIELD_MIMETYPE, NULL);
- icon = mime_icon_lookup(48, tmp ? tmp : "audio/x-generic");
- if (icon) {
- if (image_fileicon) gtk_image_set_from_pixbuf (GTK_IMAGE(image_fileicon), icon);
- g_object_unref(icon);
- }
-
- tmp = fileinfo_recursive_get_image(
- tuple_get_string(tuple, FIELD_FILE_PATH, NULL),
- tuple_get_string(tuple, FIELD_FILE_NAME, NULL), 0);
-
- if (tmp) {
- fileinfo_entry_set_image(image_artwork, tmp);
- g_free(tmp);
- }
-
- gtk_widget_set_sensitive(btn_apply, FALSE);
-
- if (label_mini_status != NULL) {
- gtk_label_set_text(GTK_LABEL(label_mini_status), "<span size=\"small\"></span>");
- gtk_label_set_use_markup(GTK_LABEL(label_mini_status), TRUE);
- }
-
- store = gtk_list_store_new(RAWDATA_N_COLS, G_TYPE_STRING, G_TYPE_STRING);
-
- for (i = 0; i < FIELD_LAST; i++) {
- gchar *key, *value;
-
- if (!tuple->values[i])
- continue;
-
- if (tuple->values[i]->type != TUPLE_INT && tuple->values[i]->value.string)
- value = g_strdup(tuple->values[i]->value.string);
- else if (tuple->values[i]->type == TUPLE_INT)
- value = g_strdup_printf("%d", tuple->values[i]->value.integer);
- else
- continue;
-
- key = g_strdup(tuple_fields[i].name);
-
- gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter,
- RAWDATA_KEY, key,
- RAWDATA_VALUE, value, -1);
-
- g_free(key);
- g_free(value);
- }
-
- /* non-standard values are stored in a dictionary. */
- MOWGLI_DICTIONARY_FOREACH(tvalue, &state, tuple->dict) {
- gchar *key, *value;
-
- if (tvalue->type != TUPLE_INT && tvalue->value.string)
- value = g_strdup(tvalue->value.string);
- else if (tvalue->type == TUPLE_INT)
- value = g_strdup_printf("%d", tvalue->value.integer);
- else
- continue;
-
- key = g_strdup(state.cur->key);
-
- gtk_list_store_append(store, &iter);
- gtk_list_store_set(store, &iter,
- RAWDATA_KEY, key,
- RAWDATA_VALUE, value, -1);
-
- g_free(key);
- g_free(value);
- }
-
- gtk_tree_view_set_model(GTK_TREE_VIEW(treeview_rawdata), GTK_TREE_MODEL(store));
- g_object_unref(store);
-
- if (!GTK_WIDGET_VISIBLE(fileinfo_win))
- gtk_widget_show(fileinfo_win);
-}
-
-static void fileinfo_show_editor_for_path (const gchar * path, InputPlugin * ip)
-{
- G_FREE_CLEAR(current_file);
- current_file = g_strdup(path);
- current_ip = ip;
-
- Tuple *tuple = input_get_song_tuple(path);
-
- if (tuple == NULL) {
- input_file_info_box(path);
- return;
- }
-
- fileinfo_show_for_tuple(tuple, TRUE);
-
- mowgli_object_unref(tuple);
-}
-
-void ui_fileinfo_show (gint playlist, gint entry)
-{
- const gchar * filename = playlist_entry_get_filename (playlist, entry);
- InputPlugin * decoder = playlist_entry_get_decoder (playlist, entry);
- Tuple * tuple;
-
- g_return_if_fail (filename != NULL);
-
- if (decoder == NULL)
- decoder = file_probe (filename, FALSE);
-
- if (decoder == NULL)
- {
- gchar * message = g_strdup_printf ("No decoder found for %s.\n",
- filename);
-
- hook_call ("interface show error", message);
- g_free (message);
- return;
- }
-
- if (decoder->file_info_box != NULL)
- decoder->file_info_box (filename);
- else if (decoder->update_song_tuple != NULL && ! vfs_is_remote (filename))
- fileinfo_show_editor_for_path (filename, decoder);
- else if ((tuple = (Tuple *) playlist_entry_get_tuple (playlist, entry)) !=
- NULL)
- fileinfo_show_for_tuple (tuple, FALSE);
- else if (decoder->get_song_tuple != NULL && (tuple = decoder->get_song_tuple
- (filename)) != NULL)
- {
- fileinfo_show_for_tuple (tuple, FALSE);
- playlist_entry_set_tuple (playlist, entry, tuple);
- }
- else
- {
- gchar * message = g_strdup_printf ("No info available for "
- "%s.\n", filename);
-
- hook_call ("interface show error", message);
- g_free (message);
- }
-}
-
-void ui_fileinfo_show_current (void)
-{
- gint playlist = playlist_get_playing ();
-
- if (playlist == -1)
- playlist = playlist_get_active ();
-
- ui_fileinfo_show (playlist, playlist_get_position (playlist));
-}
diff --git a/src/audacious/ui_fileinfo.h b/src/audacious/ui_fileinfo.h
deleted file mode 100644
index 0fc76b1..0000000
--- a/src/audacious/ui_fileinfo.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Audacious: A cross-platform multimedia player
- * Copyright (c) 2006 William Pitcock, Tony Vroon, George Averill,
- * Giacomo Lozito, Derek Pomery and Yoshiki Yazawa.
- *
- * 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 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; If not, see <http://www.gnu.org/licenses>.
- */
-
-#ifndef AUDACIOUS_UI_FILEINFO_H
-#define AUDACIOUS_UI_FILEINFO_H
-
-#include "tuple.h"
-#include "plugin.h"
-#include <glib.h>
-
-void create_fileinfo_window(void);
-gchar* fileinfo_recursive_get_image(const gchar* path, const gchar* file_name, gint depth);
-
-void ui_fileinfo_show (gint playlist, gint entry);
-void ui_fileinfo_show_current (void);
-
-#endif /* AUDACIOUS_UI_FILEINFO_H */
diff --git a/src/audacious/ui_fileinfopopup.c b/src/audacious/ui_fileinfopopup.c
deleted file mode 100644
index e357576..0000000
--- a/src/audacious/ui_fileinfopopup.c
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Audacious: A cross-platform multimedia player
- * Copyright (c) 2006 William Pitcock, Tony Vroon, George Averill,
- * Giacomo Lozito, Derek Pomery and Yoshiki Yazawa.
- *
- * 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; under version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses>.
- *
- * The Audacious team does not consider modular code linking to
- * Audacious or using our public API to be a derived work.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <glib.h>
-#include <glib/gi18n.h>
-#include <gtk/gtk.h>
-#include <string.h>
-
-#include "compatibility.h"
-
-#include "main.h"
-#include "playback.h"
-#include "playlist-new.h"
-#include "audstrings.h"
-#include "ui_fileinfopopup.h"
-#include "ui_fileinfo.h"
-
-static void
-filepopup_entry_set_text(GtkWidget *filepopup_win, const gchar *entry_name,
- const gchar *text)
-{
- GtkWidget *widget = g_object_get_data(G_OBJECT(filepopup_win), entry_name);
- g_return_if_fail(widget != NULL);
-
- gtk_label_set_text(GTK_LABEL(widget), text);
-}
-
-static void
-filepopup_entry_set_image(GtkWidget *filepopup_win, const gchar *entry_name,
- const gchar *text)
-{
- GtkWidget *widget = g_object_get_data(G_OBJECT(filepopup_win), entry_name);
- GdkPixbuf *pixbuf, *pixbuf2;
- int width, height;
- double aspect;
-
- g_return_if_fail(widget != NULL);
-
- pixbuf = gdk_pixbuf_new_from_file(text, NULL);
- g_return_if_fail(pixbuf != NULL);
-
- width = gdk_pixbuf_get_width(GDK_PIXBUF(pixbuf));
- height = gdk_pixbuf_get_height(GDK_PIXBUF(pixbuf));
-
- if (strcmp(DATA_DIR "/images/audio.png", text))
- {
- if (width == 0)
- width = 1;
-
- aspect = (double)height / (double)width;
- if (aspect > 1.0) {
- height = (int)(cfg.filepopup_pixelsize * aspect);
- width = cfg.filepopup_pixelsize;
- } else {
- height = cfg.filepopup_pixelsize;
- width = (int)(cfg.filepopup_pixelsize / aspect);
- }
-
- pixbuf2 = gdk_pixbuf_scale_simple(GDK_PIXBUF(pixbuf), width, height,
- GDK_INTERP_BILINEAR);
- g_object_unref(G_OBJECT(pixbuf));
- pixbuf = pixbuf2;
- }
-
- gtk_image_set_from_pixbuf(GTK_IMAGE(widget), GDK_PIXBUF(pixbuf));
- g_object_unref(G_OBJECT(pixbuf));
-}
-
-static gboolean
-fileinfopopup_progress_cb(gpointer filepopup_win)
-{
- GtkWidget *progressbar =
- g_object_get_data(G_OBJECT(filepopup_win), "progressbar");
- gchar *tooltip_file = g_object_get_data(G_OBJECT(filepopup_win), "file");
- gchar * current_file;
- gint length =
- GPOINTER_TO_INT(g_object_get_data(G_OBJECT(filepopup_win), "length"));
- gint playlist, entry, time;
- const gchar * filename;
-
- g_return_val_if_fail(progressbar != NULL, FALSE);
-
- playlist = playlist_get_active ();
- entry = playlist_get_position (playlist);
- filename = playlist_entry_get_filename (playlist, entry);
-
- if (filename == NULL)
- return FALSE;
-
- current_file = g_filename_from_uri (filename, NULL, NULL);
-
- if (playback_get_playing() && length != -1 &&
- current_file != NULL && tooltip_file != NULL &&
- !strcmp(tooltip_file, current_file) && cfg.filepopup_showprogressbar)
- {
- time = playback_get_time();
- gchar *progress_time =
- g_strdup_printf("%d:%02d", time / 60000, (time / 1000) % 60);
- gtk_progress_bar_set_fraction(GTK_PROGRESS_BAR(progressbar),
- (gdouble)time / (gdouble)length);
- gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progressbar), progress_time);
-
- if (!GTK_WIDGET_VISIBLE(progressbar))
- gtk_widget_show(progressbar);
-
- g_free(progress_time);
- }
- else
- {
- /* tooltip opened, but song is not the same,
- * or playback is stopped, or length is not applicabile */
- if (GTK_WIDGET_VISIBLE(progressbar))
- gtk_widget_hide(progressbar);
- }
-
- g_free( current_file );
- return TRUE;
-}
-
-static gboolean
-fileinfopopup_progress_check_active(GtkWidget *filepopup_win)
-{
- if (GPOINTER_TO_INT(g_object_get_data(G_OBJECT(filepopup_win),"progress_sid")) == 0)
- return FALSE;
- return TRUE;
-}
-
-static void
-fileinfopopup_progress_init(GtkWidget *filepopup_win)
-{
- g_object_set_data( G_OBJECT(filepopup_win) , "progress_sid" , GINT_TO_POINTER(0) );
-}
-
-static void
-fileinfopopup_progress_start(GtkWidget *filepopup_win)
-{
- gint sid =
- g_timeout_add(500, (GSourceFunc)fileinfopopup_progress_cb,
- filepopup_win);
- g_object_set_data(G_OBJECT(filepopup_win), "progress_sid",
- GINT_TO_POINTER(sid));
-}
-
-static void
-fileinfopopup_progress_stop(GtkWidget *filepopup_win)
-{
- gint sid = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(filepopup_win),
- "progress_sid"));
- if (sid != 0)
- {
- g_source_remove(sid);
- g_object_set_data(G_OBJECT(filepopup_win),"progress_sid",GINT_TO_POINTER(0));
- }
-}
-
-static void
-fileinfopopup_add_category(GtkWidget *filepopup_win,
- GtkWidget *filepopup_data_table,
- const gchar *category,
- const gchar *header_data,
- const gchar *label_data,
- const gint position)
-{
- gchar *markup;
-
- GtkWidget *filepopup_data_info_header = gtk_label_new("");
- GtkWidget *filepopup_data_info_label = gtk_label_new("");
- gtk_misc_set_alignment(GTK_MISC(filepopup_data_info_header), 0, 0.5);
- gtk_misc_set_alignment(GTK_MISC(filepopup_data_info_label), 0, 0.5);
- gtk_misc_set_padding(GTK_MISC(filepopup_data_info_header), 0, 3);
- gtk_misc_set_padding(GTK_MISC(filepopup_data_info_label), 0, 3);
-
- markup =
- g_markup_printf_escaped("<span style=\"italic\">%s</span>", category);
-
- gtk_label_set_markup(GTK_LABEL(filepopup_data_info_header), markup);
- g_free(markup);
-
- g_object_set_data(G_OBJECT(filepopup_win), header_data,
- filepopup_data_info_header);
- g_object_set_data(G_OBJECT(filepopup_win), label_data,
- filepopup_data_info_label);
- gtk_table_attach(GTK_TABLE(filepopup_data_table),
- filepopup_data_info_header,
- 0, 1, position, position + 1, GTK_FILL, 0, 0, 0);
- gtk_table_attach(GTK_TABLE(filepopup_data_table),
- filepopup_data_info_label,
- 1, 2, position, position + 1, GTK_FILL, 0, 0, 0);
-}
-
-
-
-GtkWidget *
-fileinfopopup_create(void)
-{
- GtkWidget *filepopup_win;
- GtkWidget *filepopup_hbox;
- GtkWidget *filepopup_data_image;
- GtkWidget *filepopup_data_table;
- GtkWidget *filepopup_progress;
-
- filepopup_win = gtk_window_new(GTK_WINDOW_POPUP);
- gtk_window_set_type_hint(GTK_WINDOW(filepopup_win),
- GDK_WINDOW_TYPE_HINT_TOOLTIP);
- gtk_window_set_decorated(GTK_WINDOW(filepopup_win), FALSE);
- gtk_container_set_border_width(GTK_CONTAINER(filepopup_win), 6);
-
- filepopup_hbox = gtk_hbox_new(FALSE, 0);
- gtk_container_add(GTK_CONTAINER(filepopup_win), filepopup_hbox);
-
- filepopup_data_image = gtk_image_new();
- gtk_misc_set_alignment(GTK_MISC(filepopup_data_image), 0.5, 0);
- gtk_image_set_from_file(GTK_IMAGE(filepopup_data_image),
- DATA_DIR "/images/audio.png");
-
- g_object_set_data(G_OBJECT(filepopup_win), "image_artwork",
- filepopup_data_image);
- g_object_set_data(G_OBJECT(filepopup_win), "last_artwork", NULL);
- gtk_box_pack_start(GTK_BOX(filepopup_hbox), filepopup_data_image,
- FALSE, FALSE, 0);
-
- gtk_box_pack_start(GTK_BOX(filepopup_hbox), gtk_vseparator_new(),
- FALSE, FALSE, 6);
-
- filepopup_data_table = gtk_table_new(8, 2, FALSE);
- gtk_table_set_row_spacings(GTK_TABLE(filepopup_data_table), 0);
- gtk_table_set_col_spacings(GTK_TABLE(filepopup_data_table), 6);
- gtk_box_pack_start(GTK_BOX(filepopup_hbox), filepopup_data_table,
- TRUE, TRUE, 0);
-
- fileinfopopup_add_category(filepopup_win, filepopup_data_table,
- _("Title"),
- "header_title", "label_title", 0);
- fileinfopopup_add_category(filepopup_win, filepopup_data_table,
- _("Artist"),
- "header_artist", "label_artist", 1);
- fileinfopopup_add_category(filepopup_win, filepopup_data_table,
- _("Album"),
- "header_album", "label_album", 2);
- fileinfopopup_add_category(filepopup_win, filepopup_data_table,
- _("Genre"),
- "header_genre", "label_genre", 3);
- fileinfopopup_add_category(filepopup_win, filepopup_data_table,
- _("Year"),
- "header_year", "label_year", 4);
- fileinfopopup_add_category(filepopup_win, filepopup_data_table,
- _("Track Number"),
- "header_tracknum", "label_tracknum",
- 5);
- fileinfopopup_add_category(filepopup_win, filepopup_data_table,
- _("Track Length"),
- "header_tracklen", "label_tracklen",
- 6);
-
- gtk_table_set_row_spacing(GTK_TABLE(filepopup_data_table), 6, 6);
-
- /* track progress */
- filepopup_progress = gtk_progress_bar_new();
- gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(filepopup_progress),
- GTK_PROGRESS_LEFT_TO_RIGHT);
- gtk_progress_bar_set_text(GTK_PROGRESS_BAR(filepopup_progress), "");
- gtk_table_attach(GTK_TABLE(filepopup_data_table), filepopup_progress,
- 0, 2, 7, 8, GTK_FILL, 0, 0, 0);
- g_object_set_data(G_OBJECT(filepopup_win), "file", NULL);
- g_object_set_data(G_OBJECT(filepopup_win), "progressbar",
- filepopup_progress);
- fileinfopopup_progress_init(filepopup_win);
-
- /* this will realize all widgets contained in filepopup_hbox */
- gtk_widget_show_all(filepopup_hbox);
-
- /* do not show the track progress */
- gtk_widget_hide(filepopup_progress);
-
- return filepopup_win;
-}
-
-void
-fileinfopopup_destroy(GtkWidget *filepopup_win)
-{
- gchar *last_artwork;
- fileinfopopup_progress_stop(filepopup_win);
-
- last_artwork =
- g_object_get_data(G_OBJECT(filepopup_win), "last_artwork");
- if (last_artwork != NULL)
- g_free(last_artwork);
-
- gtk_widget_destroy(filepopup_win);
-}
-
-static void
-fileinfopupup_update_data(GtkWidget *filepopup_win,
- const gchar *text,
- const gchar *label_data,
- const gchar *header_data)
-{
- if (text != NULL)
- {
- filepopup_entry_set_text(filepopup_win, label_data, text);
- gtk_widget_show(GTK_WIDGET(g_object_get_data(G_OBJECT(filepopup_win), header_data)));
- gtk_widget_show(GTK_WIDGET(g_object_get_data(G_OBJECT(filepopup_win), label_data)));
- }
- else
- {
- gtk_widget_hide(GTK_WIDGET(g_object_get_data(G_OBJECT(filepopup_win), header_data)));
- gtk_widget_hide(GTK_WIDGET(g_object_get_data(G_OBJECT(filepopup_win), label_data)));
- }
-}
-
-void
-fileinfopopup_show_from_tuple(GtkWidget *filepopup_win,
- Tuple *tuple)
-{
- gchar *tmp = NULL;
- gint x, y, x_off = 3, y_off = 3, h, w;
- gchar *length_string, *year_string, *track_string;
- gchar *last_artwork;
- const static gchar default_artwork[] = DATA_DIR "/images/audio.png";
- gint length;
- const gchar * path, * name;
-
- last_artwork =
- g_object_get_data(G_OBJECT(filepopup_win), "last_artwork");
-
- g_return_if_fail(tuple != NULL);
-
- tmp = g_object_get_data(G_OBJECT(filepopup_win), "file");
- if (tmp != NULL) {
- g_free(tmp);
- tmp = NULL;
- g_object_set_data(G_OBJECT(filepopup_win), "file", NULL);
- }
-
- path = tuple_get_string (tuple, FIELD_FILE_PATH, NULL);
-
- if (!path || strncmp (path, "file://", 7)) /* remote files not handled */
- return;
-
- path += 7;
- name = tuple_get_string (tuple, FIELD_FILE_NAME, NULL);
-
- g_object_set_data ((GObject *) filepopup_win, "file", g_build_filename
- (path, name, NULL));
-
- gtk_widget_realize(filepopup_win);
-
- if (tuple_get_string(tuple, FIELD_TITLE, NULL))
- {
- gchar *markup =
- g_markup_printf_escaped("<span style=\"italic\">%s</span>", _("Title"));
- gtk_label_set_markup(GTK_LABEL(g_object_get_data(G_OBJECT(filepopup_win), "header_title")), markup);
- g_free(markup);
- filepopup_entry_set_text(filepopup_win, "label_title", tuple_get_string(tuple, FIELD_TITLE, NULL));
- }
- else
- {
- /* display filename if track_name is not available */
- gchar *markup =
- g_markup_printf_escaped("<span style=\"italic\">%s</span>", _("Filename"));
- gtk_label_set_markup(GTK_LABEL(g_object_get_data(G_OBJECT(filepopup_win), "header_title")), markup);
- g_free(markup);
- filepopup_entry_set_text (filepopup_win, "label_title", name);
- }
-
- fileinfopupup_update_data(filepopup_win, tuple_get_string(tuple, FIELD_ARTIST, NULL),
- "label_artist", "header_artist");
- fileinfopupup_update_data(filepopup_win, tuple_get_string(tuple, FIELD_ALBUM, NULL),
- "label_album", "header_album");
- fileinfopupup_update_data(filepopup_win, tuple_get_string(tuple, FIELD_GENRE, NULL),
- "label_genre", "header_genre");
-
- length = tuple_get_int(tuple, FIELD_LENGTH, NULL);
- length_string = (length > 0) ?
- g_strdup_printf("%d:%02d", length / 60000, (length / 1000) % 60) : NULL;
- fileinfopupup_update_data(filepopup_win, length_string,
- "label_tracklen", "header_tracklen");
- g_free(length_string);
-
- if ( length > 0 )
- g_object_set_data( G_OBJECT(filepopup_win), "length" , GINT_TO_POINTER(length) );
- else
- g_object_set_data( G_OBJECT(filepopup_win), "length" , GINT_TO_POINTER(-1) );
-
- year_string = (tuple_get_int(tuple, FIELD_YEAR, NULL) == 0) ? NULL : g_strdup_printf("%d", tuple_get_int(tuple, FIELD_YEAR, NULL));
- fileinfopupup_update_data(filepopup_win, year_string,
- "label_year", "header_year");
- g_free(year_string);
-
- track_string = (tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL) == 0) ? NULL : g_strdup_printf("%d", tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL));
- fileinfopupup_update_data(filepopup_win, track_string,
- "label_tracknum", "header_tracknum");
- g_free(track_string);
-
- tmp = fileinfo_recursive_get_image (path, name, 0);
-
- /* { */
- if (tmp) { // picture found
- if (!last_artwork || strcmp(last_artwork, tmp)) { // new picture
- filepopup_entry_set_image(filepopup_win, "image_artwork", tmp);
- if (last_artwork) g_free(last_artwork);
- last_artwork = tmp;
- g_object_set_data(G_OBJECT(filepopup_win), "last_artwork", last_artwork);
- }
- else { // same picture
- }
- }
- else { // no picture found
- if (!last_artwork || strcmp(last_artwork, default_artwork)) {
- filepopup_entry_set_image(filepopup_win, "image_artwork", default_artwork);
- if (last_artwork) g_free(last_artwork);
- last_artwork = g_strdup(default_artwork);
- g_object_set_data(G_OBJECT(filepopup_win), "last_artwork", last_artwork);
- }
- else {
- }
- }
- /* } */
-
- /* start a timer that updates a progress bar if the tooltip
- is shown for the song that is being currently played */
- if (fileinfopopup_progress_check_active(filepopup_win) == FALSE)
- {
- fileinfopopup_progress_start(filepopup_win);
- /* immediately run the callback once to update progressbar status */
- fileinfopopup_progress_cb(filepopup_win);
- }
-
- gdk_window_get_pointer(gdk_get_default_root_window(), &x, &y, NULL);
- gtk_window_get_size(GTK_WINDOW(filepopup_win), &w, &h);
- if (gdk_screen_width()-(w+3) < x) x_off = (w*-1)-3;
- if (gdk_screen_height()-(h+3) < y) y_off = (h*-1)-3;
- gtk_window_move(GTK_WINDOW(filepopup_win), x + x_off, y + y_off);
-
- gtk_widget_show(filepopup_win);
-}
-
-void
-fileinfopopup_show_from_title(GtkWidget *filepopup_win, gchar *title)
-{
- Tuple * tuple = tuple_new();
- tuple_associate_string(tuple, FIELD_TITLE, NULL, title);
- fileinfopopup_show_from_tuple(filepopup_win, tuple);
- mowgli_object_unref(tuple);
- return;
-}
-
-void
-fileinfopopup_hide(GtkWidget *filepopup_win, gpointer unused)
-{
- if (GTK_WIDGET_VISIBLE(filepopup_win))
- {
- fileinfopopup_progress_stop(filepopup_win);
-
- gtk_widget_hide(filepopup_win);
-
- filepopup_entry_set_text(GTK_WIDGET(filepopup_win), "label_title", "");
- filepopup_entry_set_text(GTK_WIDGET(filepopup_win), "label_artist", "");
- filepopup_entry_set_text(GTK_WIDGET(filepopup_win), "label_album", "");
- filepopup_entry_set_text(GTK_WIDGET(filepopup_win), "label_genre", "");
- filepopup_entry_set_text(GTK_WIDGET(filepopup_win), "label_tracknum", "");
- filepopup_entry_set_text(GTK_WIDGET(filepopup_win), "label_year", "");
- filepopup_entry_set_text(GTK_WIDGET(filepopup_win), "label_tracklen", "");
-
- gtk_window_resize(GTK_WINDOW(filepopup_win), 1, 1);
- }
-}
diff --git a/src/audacious/ui_fileinfopopup.h b/src/audacious/ui_fileinfopopup.h
deleted file mode 100644
index 0b19634..0000000
--- a/src/audacious/ui_fileinfopopup.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Audacious: A cross-platform multimedia player
- * Copyright (c) 2006 William Pitcock, Tony Vroon, George Averill,
- * Giacomo Lozito, Derek Pomery and Yoshiki Yazawa.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-#ifndef AUDACIOUS_UI_FILEINFOPOPUP_H
-#define AUDACIOUS_UI_FILEINFOPOPUP_H
-
-#include "libaudcore/tuple.h"
-#include <gtk/gtk.h>
-
-/* create/destroy */
-GtkWidget* fileinfopopup_create(void);
-void fileinfopopup_destroy(GtkWidget* fileinfopopup_win);
-
-/* show/hide */
-void fileinfopopup_show_from_tuple(GtkWidget *fileinfopopup_win, Tuple *tuple);
-void fileinfopopup_show_from_title(GtkWidget *fileinfopopup_win, gchar *title);
-void fileinfopopup_hide(GtkWidget *filepopup_win, gpointer unused);
-
-#endif /* AUDACIOUS_UI_FILEINFOPOPUP_H */
diff --git a/src/audacious/ui_misc.h b/src/audacious/ui_misc.h
index 9f010ae..abf5220 100644
--- a/src/audacious/ui_misc.h
+++ b/src/audacious/ui_misc.h
@@ -18,7 +18,6 @@
*/
#include <glib/gi18n.h>
-#include <gtk/gtk.h>
#ifndef _AUDACIOUS_UI_MISC_H
diff --git a/src/audacious/ui_plugin_menu.c b/src/audacious/ui_plugin_menu.c
index 49f7e0b..5f2846a 100644
--- a/src/audacious/ui_plugin_menu.c
+++ b/src/audacious/ui_plugin_menu.c
@@ -57,7 +57,8 @@ static void static_menu_init (StaticMenu * menu)
g_object_ref (menu);
}
-GtkWidget * get_plugin_menu (gint id)
+/* GtkWidget * get_plugin_menu (gint id) */
+void * get_plugin_menu (gint id)
{
static gboolean initted = FALSE;
static GtkWidget * menus[TOTAL_PLUGIN_MENUS];
@@ -81,13 +82,15 @@ GtkWidget * get_plugin_menu (gint id)
return menus[id];
}
-gint menu_plugin_item_add (gint id, GtkWidget * item)
+/* gint menu_plugin_item_add (gint id, GtkWidget * item) */
+gint menu_plugin_item_add (gint id, void * item)
{
gtk_menu_shell_append ((GtkMenuShell *) get_plugin_menu (id), item);
return 0;
}
-gint menu_plugin_item_remove (gint id, GtkWidget * item)
+/* gint menu_plugin_item_remove (gint id, GtkWidget * item) */
+gint menu_plugin_item_remove (gint id, void * item)
{
gtk_container_remove ((GtkContainer *) get_plugin_menu (id), item);
return 0;
diff --git a/src/audacious/ui_plugin_menu.h b/src/audacious/ui_plugin_menu.h
index 9cdb267..c7377e7 100644
--- a/src/audacious/ui_plugin_menu.h
+++ b/src/audacious/ui_plugin_menu.h
@@ -1,5 +1,5 @@
/* Audacious - Cross-platform multimedia player
- * Copyright (C) 2005-2009 Audacious development team.
+ * Copyright (C) 2005-2010 Audacious development team.
*
* 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
@@ -21,9 +21,6 @@
#define AUDACIOUS_UI_PLUGIN_MENU_H
#include <glib.h>
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
#define AUDACIOUS_MENU_MAIN 0
#define AUDACIOUS_MENU_PLAYLIST 1
@@ -34,10 +31,11 @@ G_BEGIN_DECLS
#define AUDACIOUS_MENU_PLAYLIST_MISC 6
#define TOTAL_PLUGIN_MENUS 7
-GtkWidget * get_plugin_menu (gint id);
-gint menu_plugin_item_add (gint id, GtkWidget * item);
-gint menu_plugin_item_remove (gint id, GtkWidget * item);
-
-G_END_DECLS
+/* GtkWidget * get_plugin_menu (gint id); */
+void * get_plugin_menu (gint id);
+/* gint menu_plugin_item_add (gint id, GtkWidget * item); */
+gint menu_plugin_item_add (gint id, void * item);
+/* gint menu_plugin_item_remove (gint id, GtkWidget * item); */
+gint menu_plugin_item_remove (gint id, void * item);
#endif /* AUDACIOUS_UI_PLUGIN_MENU_H */
diff --git a/src/audacious/ui_preferences.c b/src/audacious/ui_preferences.c
index 45ce152..4745a3f 100644
--- a/src/audacious/ui_preferences.c
+++ b/src/audacious/ui_preferences.c
@@ -54,8 +54,6 @@
#include "ui_preferences.h"
-#include "build_stamp.h"
-
#define TITLESTRING_UPDATE_TIMEOUT 3
static void sw_volume_toggled (void);
@@ -157,6 +155,7 @@ static ComboBoxElements chardet_detector_presets[] = {
{ N_("Hebrew") , N_("Hebrew") },
{ N_("Turkish") , N_("Turkish") },
{ N_("Arabic") , N_("Arabic") },
+ { N_("Polish") , N_("Polish") },
{ N_("Universal"), N_("Universal") }
};
@@ -170,8 +169,8 @@ static ComboBoxElements bitdepth_elements[] = {
typedef struct {
void *next;
GtkWidget *container;
- char *pg_name;
- char *img_url;
+ const gchar * pg_name;
+ const gchar * img_url;
} CategoryQueueEntry;
CategoryQueueEntry *category_queue = NULL;
@@ -1561,7 +1560,9 @@ static void fill_table (GtkWidget * table, PreferencesWidget * elements, gint
}
}
-void create_widgets_with_domain (GtkBox * box, PreferencesWidget * widgets, gint
+/* void create_widgets_with_domain (GtkBox * box, PreferencesWidget * widgets,
+ gint amt, const gchar * domain) */
+void create_widgets_with_domain (void * box, PreferencesWidget * widgets, gint
amt, const gchar * domain)
{
gint x;
@@ -2552,8 +2553,8 @@ create_plugin_pages(void)
create_plugin_page(get_effect_enabled_list());
}
-GtkWidget **
-create_prefs_window(void)
+/* GtkWidget * * create_prefs_window (void) */
+void * * create_prefs_window (void)
{
gchar *aud_version_string;
@@ -2655,16 +2656,15 @@ create_prefs_window(void)
/* audacious version label */
- aud_version_string = g_strdup_printf("<span size='small'>%s (%s) (%s@%s)</span>",
- "Audacious " PACKAGE_VERSION ,
- build_stamp ,
- g_get_user_name() , g_get_host_name() );
+ aud_version_string = g_strdup_printf
+ ("<span size='small'>%s (%s)</span>", "Audacious " PACKAGE_VERSION,
+ BUILDSTAMP);
gtk_label_set_markup( GTK_LABEL(audversionlabel) , aud_version_string );
g_free(aud_version_string);
gtk_widget_show_all(vbox);
- return &prefswin;
+ return (void * *) & prefswin;
}
void
@@ -2722,8 +2722,8 @@ hide_prefs_window(void)
gtk_widget_hide(GTK_WIDGET(prefswin));
}
-static void
-prefswin_page_queue_new(GtkWidget *container, gchar *name, gchar *imgurl)
+static void prefswin_page_queue_new (GtkWidget * container, const gchar * name,
+ const gchar * imgurl)
{
CategoryQueueEntry *ent = g_new0(CategoryQueueEntry, 1);
@@ -2755,8 +2755,10 @@ prefswin_page_queue_destroy(CategoryQueueEntry *ent)
*
* - nenolod
*/
-gint
-prefswin_page_new(GtkWidget *container, gchar *name, gchar *imgurl)
+/* gint prefswin_page_new (GtkWidget * container, const gchar * name,
+ const gchar * imgurl) */
+gint prefswin_page_new (void * container, const gchar * name, const gchar *
+ imgurl)
{
GtkTreeModel *model;
GtkTreeIter iter;
diff --git a/src/audacious/ui_preferences.h b/src/audacious/ui_preferences.h
index 3ede72f..b709a81 100644
--- a/src/audacious/ui_preferences.h
+++ b/src/audacious/ui_preferences.h
@@ -20,12 +20,16 @@
#ifndef AUDACIOUS_UI_PREFERENCES_H
#define AUDACIOUS_UI_PREFERENCES_H
-GtkWidget** create_prefs_window(void);
+/* GtkWidget * * create_prefs_window (void); */
+void * * create_prefs_window (void);
void destroy_prefs_window(void);
void show_prefs_window(void);
void hide_prefs_window(void);
-gint prefswin_page_new(GtkWidget *container, gchar *name, gchar *imgurl);
+/* gint prefswin_page_new (GtkWidget * container, const gchar * name,
+ const gchar * imgurl); */
+gint prefswin_page_new (void * container, const gchar * name, const gchar *
+ imgurl);
void prefswin_page_destroy(GtkWidget *container);
#endif /* AUDACIOUS_UI_PREFERENCES_H */
diff --git a/src/audacious/util.c b/src/audacious/util.c
index 9177668..17389f9 100644
--- a/src/audacious/util.c
+++ b/src/audacious/util.c
@@ -163,9 +163,9 @@ open_ini_file(const gchar *filename)
GHashTable *section = NULL;
GString *section_name, *key_name, *value;
gpointer section_hash, key_hash;
- gchar *buffer = NULL;
+ guchar * buffer = NULL;
gsize off = 0;
- gsize filesize = 0;
+ gint64 filesize = 0;
unsigned char x[] = { 0xff, 0xfe, 0x00 };
@@ -181,7 +181,7 @@ open_ini_file(const gchar *filename)
*/
if (filesize > 2 && !memcmp(&buffer[0],&x,2))
{
- gchar *outbuf = g_malloc (filesize); /* it's safe to waste memory. */
+ guchar * outbuf = g_malloc (filesize); /* it's safe to waste memory. */
guint counter;
for (counter = 2; counter < filesize; counter += 2)
@@ -483,74 +483,6 @@ dir_foreach(const gchar * path, DirForeachFunc function,
}
/**
- * util_info_dialog:
- * @title: The title of the message to show.
- * @text: The text of the message to show.
- * @button_text: The text of the button which will close the messagebox.
- * @modal: Whether or not the messagebox should be modal.
- * @button_action: Code to execute on when the messagebox is closed, or %NULL.
- * @action_data: Optional opaque data to pass to @button_action.
- *
- * Displays a message box.
- *
- * Return value: A GTK widget handle for the message box.
- **/
-GtkWidget *
-util_info_dialog(const gchar * title, const gchar * text,
- const gchar * button_text, gboolean modal,
- GCallback button_action, gpointer action_data)
-{
- GtkWidget *dialog;
- GtkWidget *dialog_vbox, *dialog_hbox, *dialog_bbox;
- GtkWidget *dialog_bbox_b1;
- GtkWidget *dialog_textlabel;
- GtkWidget *dialog_icon;
-
- dialog = gtk_window_new(GTK_WINDOW_TOPLEVEL);
- gtk_window_set_type_hint( GTK_WINDOW(dialog) , GDK_WINDOW_TYPE_HINT_DIALOG );
- gtk_window_set_modal( GTK_WINDOW(dialog) , modal );
- gtk_window_set_title( GTK_WINDOW(dialog) , title );
- gtk_container_set_border_width( GTK_CONTAINER(dialog) , 10 );
-
- dialog_vbox = gtk_vbox_new( FALSE , 0 );
- dialog_hbox = gtk_hbox_new( FALSE , 0 );
-
- /* icon */
- dialog_icon = gtk_image_new_from_stock( GTK_STOCK_DIALOG_INFO , GTK_ICON_SIZE_DIALOG );
- gtk_box_pack_start( GTK_BOX(dialog_hbox) , dialog_icon , FALSE , FALSE , 2 );
-
- /* label */
- dialog_textlabel = gtk_label_new( text );
- /* gtk_label_set_selectable( GTK_LABEL(dialog_textlabel) , TRUE ); */
- gtk_box_pack_start( GTK_BOX(dialog_hbox) , dialog_textlabel , TRUE , TRUE , 2 );
-
- gtk_box_pack_start( GTK_BOX(dialog_vbox) , dialog_hbox , FALSE , FALSE , 2 );
- gtk_box_pack_start( GTK_BOX(dialog_vbox) , gtk_hseparator_new() , FALSE , FALSE , 4 );
-
- dialog_bbox = gtk_hbutton_box_new();
- gtk_button_box_set_layout( GTK_BUTTON_BOX(dialog_bbox) , GTK_BUTTONBOX_END );
- dialog_bbox_b1 = gtk_button_new_with_label( button_text );
- g_signal_connect_swapped( G_OBJECT(dialog_bbox_b1) , "clicked" ,
- G_CALLBACK(gtk_widget_destroy) , dialog );
- if ( button_action )
- g_signal_connect( G_OBJECT(dialog_bbox_b1) , "clicked" ,
- button_action , action_data );
-
- gtk_container_add( GTK_CONTAINER(dialog_bbox) , dialog_bbox_b1 );
- gtk_box_pack_start( GTK_BOX(dialog_vbox) , dialog_bbox , FALSE , FALSE , 0 );
-
- gtk_container_add( GTK_CONTAINER(dialog) , dialog_vbox );
-
- GTK_WIDGET_SET_FLAGS( dialog_bbox_b1 , GTK_CAN_DEFAULT);
- gtk_widget_grab_default( dialog_bbox_b1 );
-
- gtk_widget_show_all(dialog);
-
- return dialog;
-}
-
-
-/**
* util_get_localdir:
*
* Returns a string with the full path of Audacious local datadir (where config files are placed).
@@ -614,22 +546,6 @@ construct_uri(gchar *string, const gchar *playlist_name) // uri, path and anythi
return uri;
}
-/*
- * minimize number of realloc's:
- * - set N to nearest power of 2 not less then N
- * - double it
- *
- * -- asphyx
- *
- * XXX: what's so smart about this?? seems wasteful and silly. --nenolod
- */
-gpointer
-smart_realloc(gpointer ptr, gsize *size)
-{
- *size = (gsize)pow(2, ceil(log(*size) / log(2)) + 1);
- return g_realloc(ptr, *size);
-}
-
/* local files -- not URI's */
gint file_get_mtime (const gchar * filename)
{
diff --git a/src/audacious/util.h b/src/audacious/util.h
index e7df139..e02dc93 100644
--- a/src/audacious/util.h
+++ b/src/audacious/util.h
@@ -71,18 +71,10 @@ gboolean text_get_extents(const gchar * fontname, const gchar * text,
guint gint_count_digits(gint n);
-
-GtkWidget *util_info_dialog(const gchar * title, const gchar * text,
- const gchar * button_text, gboolean modal, GCallback button_action,
- gpointer action_data);
-
gchar *util_get_localdir(void);
gchar *construct_uri(gchar *string, const gchar *playlist_name);
-/* minimizes number of realloc's */
-gpointer smart_realloc(gpointer ptr, gsize *size);
-
gint file_get_mtime (const gchar * filename);
void make_directory(const gchar * path, mode_t mode);
diff --git a/src/audacious/visualization.c b/src/audacious/visualization.c
index 038d2eb..e55a95f 100644
--- a/src/audacious/visualization.c
+++ b/src/audacious/visualization.c
@@ -26,6 +26,7 @@
#include "visualization.h"
#include <glib.h>
+#include <gtk/gtk.h>
#include <math.h>
#include <string.h>
diff --git a/src/audtool/Makefile b/src/audtool/Makefile
index 9ba6290..df743a1 100644
--- a/src/audtool/Makefile
+++ b/src/audtool/Makefile
@@ -29,7 +29,7 @@ LIBS += ${DBUS_LIBS} \
install-extra:
if test -h "${DESTDIR}${bindir}/audtool" ; then ${RM} "${DESTDIR}${bindir}/audtool" ; fi
mkdir -p "${DESTDIR}${bindir}"
- ${LN_S} "${DESTDIR}${bindir}/audtool2" "${DESTDIR}${bindir}/audtool"
+ ${LN_S} audtool2 "${DESTDIR}${bindir}/audtool"
uninstall-extra:
if test -h "${DESTDIR}${bindir}/audtool" ; then ${RM} "${DESTDIR}${bindir}/audtool" ; fi
diff --git a/src/libaudacious++/Makefile b/src/libaudacious++/Makefile
deleted file mode 100644
index e50f022..0000000
--- a/src/libaudacious++/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-PACKAGE = audacious++
-STATIC_LIB = libaudacious++.a
-SRCS = plugin.cxx
-
-include ../../buildsys.mk
-include ../../extra.mk
diff --git a/src/libaudacious++/README b/src/libaudacious++/README
deleted file mode 100644
index 6f34c43..0000000
--- a/src/libaudacious++/README
+++ /dev/null
@@ -1 +0,0 @@
-this is a work in progress. it's not GPL yet. don't use it. --nenolod
diff --git a/src/libaudacious++/plugin.h b/src/libaudacious++/plugin.h
deleted file mode 100644
index a915771..0000000
--- a/src/libaudacious++/plugin.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2008 William Pitcock <nenolod@sacredspiral.co.uk>
- *
- * [insert GPL license here later]
- */
-
-#ifndef __AUDACIOUSXX__PLUGIN_H_GUARD
-#define __AUDACIOUSXX__PLUGIN_H_GUARD
-
-#include <string>
-
-namespace Audacious {
-
-class Plugin {
-private:
- std::string name;
- std::string description;
-
-public:
- Plugin(std::string name_, std::string description_);
- ~Plugin();
-};
-
-class VisPlugin : Plugin {
-private:
- int pcm_channels;
- int freq_channels;
-
-public:
- VisPlugin(std::string name_, std::string description, int pc, int fc);
- ~VisPlugin();
-};
-
-};
-
-#endif
diff --git a/src/libaudcore/audio.c b/src/libaudcore/audio.c
index c4b8084..1975cfe 100644
--- a/src/libaudcore/audio.c
+++ b/src/libaudcore/audio.c
@@ -28,7 +28,7 @@ static void NAME (TYPE * in, gfloat * out, gint samples) \
{ \
TYPE * end = in + samples; \
while (in < end) \
- * out ++ = (gfloat) (TYPE) (SWAP (* in ++) - OFFSET) / RANGE; \
+ * out ++ = (TYPE) (SWAP (* in ++) - OFFSET) / (gdouble) RANGE; \
}
#define TO_INT_LOOP(NAME, TYPE, SWAP, OFFSET, RANGE) \
@@ -38,7 +38,7 @@ static void NAME (gfloat * in, TYPE * out, gint samples) \
while (in < end) \
{ \
float f = * in ++; \
- * out ++ = SWAP (OFFSET + (TYPE) (CLAMP (f, -1, 1) * RANGE)); \
+ * out ++ = SWAP (OFFSET + (TYPE) (CLAMP (f, -1, 1) * (gdouble) RANGE)); \
} \
}
diff --git a/src/libaudcore/audstrings.c b/src/libaudcore/audstrings.c
index 04b8377..b7428fe 100644
--- a/src/libaudcore/audstrings.c
+++ b/src/libaudcore/audstrings.c
@@ -93,20 +93,6 @@ str_replace_drive_letter(gchar * str)
return str;
}
-static gchar *
-str_replace_char(gchar * str, gchar o, gchar n)
-{
- gchar *match;
-
- g_return_val_if_fail(str != NULL, NULL);
-
- match = str;
- while ((match = strchr(match, o)) != NULL)
- *match = n;
-
- return str;
-}
-
gchar *
str_append(gchar * str, const gchar * add_str)
{
@@ -312,7 +298,7 @@ convert_dos_path(gchar * path)
str_replace_drive_letter(path);
/* replace '\' with '/' */
- str_replace_char(path, '\\', '/');
+ string_replace_char (path, '\\', '/');
return path;
}
@@ -377,6 +363,12 @@ filename_split_subtune(const gchar * filename, gint * track)
return result;
}
+void string_replace_char (gchar * string, gchar old_str, gchar new_str)
+{
+ while ((string = strchr (string, old_str)) != NULL)
+ * string = new_str;
+}
+
static gchar get_hex_digit(gchar **get)
{
gchar c = **get;
@@ -394,6 +386,7 @@ static gchar get_hex_digit(gchar **get)
return c - '0';
}
+/* modifies string in place */
void string_decode_percent(gchar *string)
{
gchar *get = string;
@@ -411,6 +404,58 @@ void string_decode_percent(gchar *string)
*set = 0;
}
+/* we encode any character except the "unreserved" characters of RFC 3986 and
+ * (optionally) the forward slash */
+static gboolean is_legal_char (gchar c, gboolean is_filename)
+{
+ return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <=
+ '9') || (strchr ("-_.~", c) != NULL) || (is_filename && c == '/');
+}
+
+static gchar make_hex_digit (gint i)
+{
+ if (i < 10)
+ return '0' + i;
+ else
+ return ('A' - 10) + i;
+}
+
+/* is_filename specifies whether the forward slash should be left intact */
+/* returns string allocated with g_malloc */
+gchar * string_encode_percent (const gchar * string, gboolean is_filename)
+{
+ gint length = 0;
+ const gchar * get;
+ gchar c;
+ gchar * new, * set;
+
+ for (get = string; (c = * get); get ++)
+ {
+ if (is_legal_char (c, is_filename))
+ length ++;
+ else
+ length += 3;
+ }
+
+ new = g_malloc (length + 1);
+ set = new;
+
+ for (get = string; (c = * get); get ++)
+ {
+ if (is_legal_char (c, is_filename))
+ * set ++ = c;
+ else
+ {
+ * set ++ = '%';
+ * set ++ = make_hex_digit (((guchar) c) >> 4);
+ * set ++ = make_hex_digit (c & 0xF);
+ }
+ }
+
+ * set = 0;
+ return new;
+}
+
void string_cut_extension(gchar *string)
{
gchar *period = strrchr(string, '.');
@@ -464,3 +509,28 @@ gint string_compare (const gchar * a, const gchar * b)
return 0;
}
+
+const void * memfind (const void * mem, gint size, const void * token, gint
+ length)
+{
+ if (! length)
+ return mem;
+
+ size -= length - 1;
+
+ while (size > 0)
+ {
+ const void * maybe = memchr (mem, * (guchar *) token, size);
+
+ if (maybe == NULL)
+ return NULL;
+
+ if (! memcmp (maybe, token, length))
+ return maybe;
+
+ size -= (guchar *) maybe + 1 - (guchar *) mem;
+ mem = (guchar *) maybe + 1;
+ }
+
+ return NULL;
+}
diff --git a/src/libaudcore/audstrings.h b/src/libaudcore/audstrings.h
index e96d52f..5baf067 100644
--- a/src/libaudcore/audstrings.h
+++ b/src/libaudcore/audstrings.h
@@ -60,10 +60,15 @@ extern gchar *(*chardet_to_utf8)(const gchar *str, gssize len,
gchar *filename_get_subtune(const gchar * filename, gint * track);
gchar *filename_split_subtune(const gchar * filename, gint * track);
-void string_decode_percent(gchar *string);
+void string_replace_char (gchar * string, gchar old_str, gchar new_str);
+void string_decode_percent (gchar * string);
+gchar * string_encode_percent (const gchar * string, gboolean is_filename);
void string_cut_extension(gchar *string);
gint string_compare (const gchar * a, const gchar * b);
+const void * memfind (const void * mem, gint size, const void * token, gint
+ length);
+
G_END_DECLS
#endif /* AUDACIOUS_STRINGS_H */
diff --git a/src/libaudcore/index.c b/src/libaudcore/index.c
index db1cea8..9344e7b 100644
--- a/src/libaudcore/index.c
+++ b/src/libaudcore/index.c
@@ -1,12 +1,12 @@
/*
* index.c
- * Copyright 2009 John Lindgren
+ * Copyright 2009-2010 John Lindgren
*
* This file is part of Audacious.
*
* Audacious 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, version 3 of the License.
+ * Foundation, version 2 or version 3 of the License.
*
* Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
@@ -29,7 +29,9 @@
struct index
{
void * * data;
- gint length, size;
+ gint count, size;
+ gint (* compare) (const void * a, const void * b, void * data);
+ void * compare_data;
};
struct index * index_new (void)
@@ -37,8 +39,10 @@ struct index * index_new (void)
struct index * index = g_malloc (sizeof (struct index));
index->data = NULL;
- index->length = 0;
+ index->count = 0;
index->size = 0;
+ index->compare = NULL;
+ index->compare_data = NULL;
return index;
}
@@ -51,7 +55,7 @@ void index_free (struct index * index)
gint index_count (struct index * index)
{
- return index->length;
+ return index->count;
}
void index_set (struct index * index, gint at, void * value)
@@ -80,12 +84,12 @@ static void resize_to (struct index * index, gint size)
}
}
-static void make_room (struct index * index, gint at, gint length)
+static void make_room (struct index * index, gint at, gint count)
{
- resize_to (index, index->length + length);
- memmove (index->data + at + length, index->data + at, sizeof (void *) *
- (index->length - at));
- index->length += length;
+ resize_to (index, index->count + count);
+ memmove (index->data + at + count, index->data + at, sizeof (void *) *
+ (index->count - at));
+ index->count += count;
}
void index_insert (struct index * index, gint at, void * value)
@@ -96,35 +100,80 @@ void index_insert (struct index * index, gint at, void * value)
void index_append (struct index * index, void * value)
{
- resize_to (index, index->length + 1);
- index->data[index->length] = value;
- index->length ++;
+ index_insert (index, index->count, value);
+}
+
+void index_copy_set (struct index * source, gint from, struct index * target,
+ gint to, gint count)
+{
+ memcpy (target->data + to, source->data + from, sizeof (void *) * count);
+}
+
+void index_copy_insert (struct index * source, gint from, struct index * target,
+ gint to, gint count)
+{
+ make_room (target, to, count);
+ memcpy (target->data + to, source->data + from, sizeof (void *) * count);
+}
+
+void index_copy_append (struct index * source, gint from, struct index * target,
+ gint count)
+{
+ index_copy_insert (source, from, target, target->count, count);
}
void index_merge_insert (struct index * first, gint at, struct index * second)
{
- make_room (first, at, second->length);
- memcpy (first->data + at, second->data, sizeof (void *) * second->length);
+ index_copy_insert (second, 0, first, at, second->count);
}
void index_merge_append (struct index * first, struct index * second)
{
- resize_to (first, first->length + second->length);
- memcpy (first->data + first->length, second->data, sizeof (void *) *
- second->length);
- first->length += second->length;
+ index_copy_insert (second, 0, first, first->count, second->count);
+}
+
+void index_move (struct index * index, gint from, gint to, gint count)
+{
+ memmove (index->data + to, index->data + from, sizeof (void *) * count);
}
-void index_delete (struct index * index, gint at, gint length)
+void index_delete (struct index * index, gint at, gint count)
{
- index->length -= length;
- memmove (index->data + at, index->data + at + length, sizeof (void *) *
- (index->length - at));
+ index->count -= count;
+ memmove (index->data + at, index->data + at + count, sizeof (void *) *
+ (index->count - at));
+}
+
+static gint index_compare (const void * a, const void * b, void * _compare)
+{
+ gint (* compare) (const void *, const void *) = _compare;
+
+ return compare (* (const void * *) a, * (const void * *) b);
+}
+
+void index_sort (struct index * index, gint (* compare) (const void *, const
+ void *))
+{
+ g_qsort_with_data (index->data, index->count, sizeof (void *),
+ index_compare, compare);
+}
+
+static gint index_compare_with_data (const void * a, const void * b, void *
+ _index)
+{
+ struct index * index = _index;
+
+ return index->compare (* (const void * *) a, * (const void * *) b,
+ index->compare_data);
}
-void index_sort (struct index * index, gint (* compare) (const void * *, const
- void * *))
+void index_sort_with_data (struct index * index, gint (* compare)
+ (const void * a, const void * b, void * data), void * data)
{
- qsort (index->data, index->length, sizeof (void *), (gint (*) (const void *,
- const void *)) compare);
+ index->compare = compare;
+ index->compare_data = data;
+ g_qsort_with_data (index->data, index->count, sizeof (void *),
+ index_compare_with_data, index);
+ index->compare = NULL;
+ index->compare_data = NULL;
}
diff --git a/src/libaudcore/index.h b/src/libaudcore/index.h
index e219595..67b1781 100644
--- a/src/libaudcore/index.h
+++ b/src/libaudcore/index.h
@@ -1,12 +1,12 @@
/*
* index.h
- * Copyright 2009 John Lindgren
+ * Copyright 2009-2010 John Lindgren
*
* This file is part of Audacious.
*
* Audacious 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, version 3 of the License.
+ * Foundation, version 2 or version 3 of the License.
*
* Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
@@ -31,10 +31,19 @@ void index_set (struct index * index, gint at, void * value);
void * index_get (struct index * index, gint at);
void index_insert (struct index * index, gint at, void * value);
void index_append (struct index * index, void * value);
+void index_copy_set (struct index * source, gint from, struct index * target,
+ gint to, gint count);
+void index_copy_insert (struct index * source, gint from, struct index * target,
+ gint to, gint count);
+void index_copy_append (struct index * source, gint from, struct index * target,
+ gint count);
void index_merge_insert (struct index * first, gint at, struct index * second);
void index_merge_append (struct index * first, struct index * second);
-void index_delete (struct index * index, gint at, gint length);
-void index_sort (struct index * index, gint (* compare) (const void * *, const
- void * *));
+void index_move (struct index * index, gint from, gint to, gint count);
+void index_delete (struct index * index, gint at, gint count);
+void index_sort (struct index * index, gint (* compare) (const void * a,
+ const void * b));
+void index_sort_with_data (struct index * index, gint (* compare)
+ (const void * a, const void * b, void * data), void * data);
#endif
diff --git a/src/libaudcore/tuple.c b/src/libaudcore/tuple.c
index 8d47d49..ef360be 100644
--- a/src/libaudcore/tuple.c
+++ b/src/libaudcore/tuple.c
@@ -63,6 +63,15 @@ const TupleBasicType tuple_fields[FIELD_LAST] = {
{ "segment-start", TUPLE_INT },
{ "segment-end", TUPLE_INT },
+
+ { "gain-album-gain", TUPLE_INT },
+ { "gain-album-peak", TUPLE_INT },
+ { "gain-track-gain", TUPLE_INT },
+ { "gain-track-peak", TUPLE_INT },
+ { "gain-gain-unit", TUPLE_INT },
+ { "gain-peak-unit", TUPLE_INT },
+
+ { "composer", TUPLE_STRING },
};
@@ -162,7 +171,7 @@ tuple_new(void)
Tuple *tuple;
TUPLE_LOCK_WRITE();
-
+
tuple = tuple_new_unlocked();
TUPLE_UNLOCK_WRITE();
@@ -392,7 +401,7 @@ tuple_associate_data(Tuple *tuple, const gint cnfield, const gchar *field, Tuple
/**
* Associates copy of given string to a field in specified #Tuple.
* If field already exists, old value is freed and replaced.
- *
+ *
* Desired field can be specified either by key name or if it is
* one of basic fields, by #TupleBasicType index.
*
@@ -424,7 +433,7 @@ tuple_associate_string(Tuple *tuple, const gint nfield, const gchar *field, cons
* Associates given string to a field in specified #Tuple. The caller
* gives up ownership of the string. If field already exists, old
* value is freed and replaced.
- *
+ *
* Desired field can be specified either by key name or if it is
* one of basic fields, by #TupleBasicType index.
*
diff --git a/src/libaudcore/tuple.h b/src/libaudcore/tuple.h
index 338ebd9..4823cb2 100644
--- a/src/libaudcore/tuple.h
+++ b/src/libaudcore/tuple.h
@@ -67,6 +67,21 @@ enum {
FIELD_SEGMENT_START,
FIELD_SEGMENT_END,
+ /* Preserving replay gain information accurately is a challenge since there
+ * are several differents formats around. We use an integer fraction, with
+ * the denominator stored in the *_UNIT fields. For example, if ALBUM_GAIN
+ * is 512 and GAIN_UNIT is 256, then the album gain is +2 dB. If TRACK_PEAK
+ * is 787 and PEAK_UNIT is 1000, then the peak volume is 0.787 in a -1.0 to
+ * 1.0 range. */
+ FIELD_GAIN_ALBUM_GAIN,
+ FIELD_GAIN_ALBUM_PEAK,
+ FIELD_GAIN_TRACK_GAIN,
+ FIELD_GAIN_TRACK_PEAK,
+ FIELD_GAIN_GAIN_UNIT,
+ FIELD_GAIN_PEAK_UNIT,
+
+ FIELD_COMPOSER, /**< Composer of song, if different than artist. */
+
/* Special field, must always be last */
FIELD_LAST
};
diff --git a/src/libaudcore/vfs.c b/src/libaudcore/vfs.c
index e6d929a..b901d0e 100644
--- a/src/libaudcore/vfs.c
+++ b/src/libaudcore/vfs.c
@@ -37,14 +37,10 @@ GList *vfs_transports = NULL; /* temporary. -nenolod */
* Registers a #VFSConstructor vtable with the VFS system.
*
* @param vtable The #VFSConstructor vtable to register.
- * @return TRUE on success, FALSE on failure.
*/
-gboolean
-vfs_register_transport(VFSConstructor *vtable)
+void vfs_register_transport (VFSConstructor * vtable)
{
- vfs_transports = g_list_append(vfs_transports, vtable);
-
- return TRUE;
+ vfs_transports = g_list_append (vfs_transports, vtable);
}
static VFSConstructor *
@@ -70,7 +66,7 @@ vfs_get_constructor(const gchar *path)
/* No transport vtable has been registered, bail. */
if (vtable == NULL)
g_warning("Could not open '%s', no transport plugin available.", path);
-
+
return vtable;
}
@@ -91,7 +87,7 @@ vfs_fopen(const gchar * path,
if (path == NULL || mode == NULL || (vtable = vfs_get_constructor(path)) == NULL)
return NULL;
-
+
file = vtable->vfs_fopen_impl(path, mode);
if (file == NULL)
@@ -139,11 +135,7 @@ vfs_fclose(VFSFile * file)
* @param file #VFSFile object that represents the VFS stream.
* @return The number of elements succesfully read.
*/
-gsize
-vfs_fread(gpointer ptr,
- gsize size,
- gsize nmemb,
- VFSFile * file)
+gint64 vfs_fread (void * ptr, gint64 size, gint64 nmemb, VFSFile * file)
{
if (file == NULL)
return 0;
@@ -160,11 +152,7 @@ vfs_fread(gpointer ptr,
* @param file #VFSFile object that represents the VFS stream.
* @return The number of elements succesfully written.
*/
-gsize
-vfs_fwrite(gconstpointer ptr,
- gsize size,
- gsize nmemb,
- VFSFile * file)
+gint64 vfs_fwrite (const void * ptr, gint64 size, gint64 nmemb, VFSFile * file)
{
if (file == NULL)
return 0;
@@ -218,7 +206,7 @@ vfs_ungetc(gint c, VFSFile *file)
*/
gint
vfs_fseek(VFSFile * file,
- glong offset,
+ gint64 offset,
gint whence)
{
if (file == NULL)
@@ -278,13 +266,12 @@ vfs_feof(VFSFile * file)
* @param length The length to truncate at.
* @return On success, 0. Otherwise, -1.
*/
-gint
-vfs_truncate(VFSFile * file, glong length)
+gint vfs_ftruncate (VFSFile * file, gint64 length)
{
if (file == NULL)
return -1;
- return file->base->vfs_truncate_impl(file, length);
+ return file->base->vfs_ftruncate_impl(file, length);
}
/**
@@ -293,7 +280,7 @@ vfs_truncate(VFSFile * file, glong length)
* @param file #VFSFile object that represents the VFS stream.
* @return On success, the size of the file in bytes. Otherwise, -1.
*/
-off_t
+gint64
vfs_fsize(VFSFile * file)
{
if (file == NULL)
@@ -314,7 +301,7 @@ vfs_get_metadata(VFSFile * file, const gchar * field)
{
if (file == NULL)
return NULL;
-
+
if (file->base->vfs_get_metadata_impl)
return file->base->vfs_get_metadata_impl(file, field);
return NULL;
diff --git a/src/libaudcore/vfs.h b/src/libaudcore/vfs.h
index f268550..fc97884 100644
--- a/src/libaudcore/vfs.h
+++ b/src/libaudcore/vfs.h
@@ -1,6 +1,6 @@
/*
* Audacious
- * Copyright (c) 2006-2007 Audacious team
+ * Copyright (c) 2006-2010 Audacious team
*
* 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
@@ -44,13 +44,13 @@ typedef struct _VFSConstructor VFSConstructor;
* similar in purpose as stdio FILE
*/
struct _VFSFile {
- gchar *uri; /**< The URI of the stream */
- gpointer handle; /**< Opaque data used by the transport plugins */
- VFSConstructor *base; /**< The base vtable used for VFS functions */
- gint ref; /**< The amount of references that the VFSFile object has */
+ gchar *uri; /**< The URI of the stream */
+ gpointer handle; /**< Opaque data used by the transport plugins */
+ VFSConstructor *base; /**< The base vtable used for VFS functions */
+ gint ref; /**< The amount of references that the VFSFile object has */
};
-/**
+/**
* @struct _VFSConstructor
* #VFSConstructor objects contain the base vtables used for extrapolating
* a VFS stream. #VFSConstructor objects should be considered %virtual in
@@ -58,103 +58,97 @@ struct _VFSFile {
*/
struct _VFSConstructor {
/** The URI identifier, e.g. "file" would handle "file://" streams. */
- gchar *uri_id;
- /** A function pointer which points to a fopen implementation. */
- VFSFile *(*vfs_fopen_impl)(const gchar *path,
- const gchar *mode);
+ gchar * uri_id;
+
+ /** A function pointer which points to a fopen implementation. */
+ VFSFile * (* vfs_fopen_impl) (const gchar * filename, const gchar * mode);
/** A function pointer which points to a fclose implementation. */
- gint (*vfs_fclose_impl)(VFSFile * file);
- /** A function pointer which points to a fread implementation. */
- gsize (*vfs_fread_impl)(gpointer ptr, gsize size,
- gsize nmemb, VFSFile *file);
+ gint (* vfs_fclose_impl) (VFSFile * file);
+
+ /** A function pointer which points to a fread implementation. */
+ gint64 (* vfs_fread_impl) (void * ptr, gint64 size, gint64 nmemb, VFSFile *
+ file);
/** A function pointer which points to a fwrite implementation. */
- gsize (*vfs_fwrite_impl)(gconstpointer ptr, gsize size,
- gsize nmemb, VFSFile *file);
+ gint64 (* vfs_fwrite_impl) (const void * ptr, gint64 size, gint64 nmemb,
+ VFSFile * file);
+
/** A function pointer which points to a getc implementation. */
- gint (*vfs_getc_impl)(VFSFile *stream);
+ gint (* vfs_getc_impl) (VFSFile * stream);
/** A function pointer which points to an ungetc implementation. */
- gint (*vfs_ungetc_impl)(gint c, VFSFile *stream);
+ gint (* vfs_ungetc_impl) (gint c, VFSFile * stream);
+
/** A function pointer which points to a fseek implementation. */
- gint (*vfs_fseek_impl)(VFSFile *file, glong offset, gint whence);
- /** function pointer which points to a rewind implementation. */
- void (*vfs_rewind_impl)(VFSFile *file);
+ gint (* vfs_fseek_impl) (VFSFile * file, gint64 offset, gint whence);
+ /** function pointer which points to a rewind implementation. */
+ void (* vfs_rewind_impl) (VFSFile * file);
/** A function pointer which points to a ftell implementation. */
- glong (*vfs_ftell_impl)(VFSFile *file);
- /** A function pointer which points to a feof implementation. */
- gboolean (*vfs_feof_impl)(VFSFile *file);
- /** A function pointer which points to a ftruncate implementation. */
- gboolean (*vfs_truncate_impl)(VFSFile *file, glong length);
- /** A function pointer which points to a fsize implementation. */
- off_t (*vfs_fsize_impl)(VFSFile *file);
- /** A function pointer which points to a (stream) metadata fetching implementation. */
- gchar *(*vfs_get_metadata_impl)(VFSFile *file, const gchar * field);
+ gint64 (* vfs_ftell_impl) (VFSFile * file);
+ /** A function pointer which points to a feof implementation. */
+ gboolean (* vfs_feof_impl) (VFSFile * file);
+ /** A function pointer which points to a ftruncate implementation. */
+ gint (* vfs_ftruncate_impl) (VFSFile * file, gint64 length);
+ /** A function pointer which points to a fsize implementation. */
+ gint64 (* vfs_fsize_impl) (VFSFile * file);
+
+ /** A function pointer which points to a (stream) metadata fetching implementation. */
+ gchar * (* vfs_get_metadata_impl) (VFSFile * file, const gchar * field);
};
-
-extern VFSFile * vfs_fopen(const gchar * path,
- const gchar * mode);
-extern gint vfs_fclose(VFSFile * file);
-
-extern VFSFile * vfs_dup(VFSFile *in);
-
-extern gsize vfs_fread(gpointer ptr,
- gsize size,
- gsize nmemb,
- VFSFile * file);
-extern gsize vfs_fwrite(gconstpointer ptr,
- gsize size,
- gsize nmemb,
- VFSFile *file);
-
-extern gint vfs_getc(VFSFile *stream);
-extern gint vfs_ungetc(gint c,
- VFSFile *stream);
-extern gchar *vfs_fgets(gchar *s,
- gint n,
- VFSFile *stream);
-
-extern gint vfs_fseek(VFSFile * file,
- glong offset,
- gint whence);
-extern void vfs_rewind(VFSFile * file);
-extern glong vfs_ftell(VFSFile * file);
-extern gboolean vfs_feof(VFSFile * file);
-
-extern gboolean vfs_file_test(const gchar * path,
- GFileTest test);
-
-extern gboolean vfs_is_writeable(const gchar * path);
-
-extern gboolean vfs_truncate(VFSFile * file, glong length);
-
-extern off_t vfs_fsize(VFSFile * file);
-
-extern gchar *vfs_get_metadata(VFSFile * file, const gchar * field);
-
-extern gint vfs_fprintf(VFSFile *stream, gchar const *format, ...)
- __attribute__ ((__format__ (__printf__, 2, 3)));
-
-extern gboolean vfs_register_transport(VFSConstructor *vtable);
-
-extern void vfs_file_get_contents(const gchar *filename, gchar **buf, gsize *size);
-
-extern gboolean vfs_is_remote(const gchar * path);
-
-extern gboolean vfs_is_streaming(VFSFile *file);
-
-extern gboolean vfs_fget_le16(guint16 *value, VFSFile *stream);
-extern gboolean vfs_fget_le32(guint32 *value, VFSFile *stream);
-extern gboolean vfs_fget_le64(guint64 *value, VFSFile *stream);
-extern gboolean vfs_fget_be16(guint16 *value, VFSFile *stream);
-extern gboolean vfs_fget_be32(guint32 *value, VFSFile *stream);
-extern gboolean vfs_fget_be64(guint64 *value, VFSFile *stream);
-
-extern gboolean vfs_fput_le16(guint16 value, VFSFile *stream);
-extern gboolean vfs_fput_le32(guint32 value, VFSFile *stream);
-extern gboolean vfs_fput_le64(guint64 value, VFSFile *stream);
-extern gboolean vfs_fput_be16(guint16 value, VFSFile *stream);
-extern gboolean vfs_fput_be32(guint32 value, VFSFile *stream);
-extern gboolean vfs_fput_be64(guint64 value, VFSFile *stream);
+#ifdef __GNUC__
+#define WARN_RETURN __attribute__ ((warn_unused_result))
+#else
+#define WARN_RETURN
+#endif
+
+VFSFile * vfs_fopen (const gchar * path, const gchar * mode) WARN_RETURN;
+VFSFile * vfs_dup (VFSFile * in) WARN_RETURN;
+gint vfs_fclose (VFSFile * file);
+
+gint64 vfs_fread (void * ptr, gint64 size, gint64 nmemb, VFSFile * file)
+ WARN_RETURN;
+gint64 vfs_fwrite (const void * ptr, gint64 size, gint64 nmemb, VFSFile * file)
+ WARN_RETURN;
+
+gint vfs_getc (VFSFile * stream) WARN_RETURN;
+gint vfs_ungetc (gint c, VFSFile * stream) WARN_RETURN;
+gchar * vfs_fgets (gchar * s, gint n, VFSFile * stream) WARN_RETURN;
+gboolean vfs_feof (VFSFile * file) WARN_RETURN;
+gint vfs_fprintf (VFSFile * stream, gchar const * format, ...) __attribute__
+ ((__format__ (__printf__, 2, 3)));
+
+gint vfs_fseek (VFSFile * file, gint64 offset, gint whence) WARN_RETURN;
+void vfs_rewind (VFSFile * file);
+glong vfs_ftell (VFSFile * file) WARN_RETURN;
+gint64 vfs_fsize (VFSFile * file) WARN_RETURN;
+gint vfs_ftruncate (VFSFile * file, gint64 length) WARN_RETURN;
+
+gboolean vfs_fget_le16 (guint16 * value, VFSFile * stream) WARN_RETURN;
+gboolean vfs_fget_le32 (guint32 * value, VFSFile * stream) WARN_RETURN;
+gboolean vfs_fget_le64 (guint64 * value, VFSFile * stream) WARN_RETURN;
+gboolean vfs_fget_be16 (guint16 * value, VFSFile * stream) WARN_RETURN;
+gboolean vfs_fget_be32 (guint32 * value, VFSFile * stream) WARN_RETURN;
+gboolean vfs_fget_be64 (guint64 * value, VFSFile * stream) WARN_RETURN;
+
+gboolean vfs_fput_le16 (guint16 value, VFSFile * stream) WARN_RETURN;
+gboolean vfs_fput_le32 (guint32 value, VFSFile * stream) WARN_RETURN;
+gboolean vfs_fput_le64 (guint64 value, VFSFile * stream) WARN_RETURN;
+gboolean vfs_fput_be16 (guint16 value, VFSFile * stream) WARN_RETURN;
+gboolean vfs_fput_be32 (guint32 value, VFSFile * stream) WARN_RETURN;
+gboolean vfs_fput_be64 (guint64 value, VFSFile * stream) WARN_RETURN;
+
+gboolean vfs_is_streaming (VFSFile * file) WARN_RETURN;
+gchar * vfs_get_metadata (VFSFile * file, const gchar * field) WARN_RETURN;
+
+gboolean vfs_file_test (const gchar * path, GFileTest test) WARN_RETURN;
+gboolean vfs_is_writeable (const gchar * path) WARN_RETURN;
+gboolean vfs_is_remote (const gchar * path) WARN_RETURN;
+
+void vfs_file_get_contents (const gchar * filename, guchar * * buf, gint64 *
+ size);
+
+void vfs_register_transport (VFSConstructor * vtable);
+
+#undef WARN_RETURN
G_END_DECLS
diff --git a/src/libaudcore/vfs_buffer.c b/src/libaudcore/vfs_buffer.c
index 322f5a0..ef2ad8f 100644
--- a/src/libaudcore/vfs_buffer.c
+++ b/src/libaudcore/vfs_buffer.c
@@ -40,11 +40,8 @@ buffer_vfs_fclose_impl(VFSFile * file)
return 0;
}
-static gsize
-buffer_vfs_fread_impl(gpointer i_ptr,
- gsize size,
- gsize nmemb,
- VFSFile * file)
+static gint64 buffer_vfs_fread_impl (void * i_ptr, gint64 size, gint64 nmemb,
+ VFSFile * file)
{
VFSBuffer *handle;
guchar *i;
@@ -56,7 +53,7 @@ buffer_vfs_fread_impl(gpointer i_ptr,
handle = (VFSBuffer *) file->handle;
- for (i = ptr; (gsize) (i - ptr) < nmemb * size &&
+ for (i = ptr; (gsize) (i - ptr) < nmemb * size &&
(gsize) (i - ptr) <= handle->size;
i++, handle->iter++)
{
@@ -67,11 +64,8 @@ buffer_vfs_fread_impl(gpointer i_ptr,
return (read / size);
}
-static gsize
-buffer_vfs_fwrite_impl(gconstpointer i_ptr,
- gsize size,
- gsize nmemb,
- VFSFile * file)
+static gint64 buffer_vfs_fwrite_impl (const void * i_ptr, gint64 size, gint64
+ nmemb, VFSFile * file)
{
VFSBuffer *handle;
const guchar *i;
@@ -233,7 +227,7 @@ vfs_buffer_new(gpointer data, gsize size)
g_free(handle);
return NULL;
}
-
+
buffer->data = data;
buffer->iter = data;
buffer->end = (guchar *) data + size;
diff --git a/src/libaudcore/vfs_buffered_file.c b/src/libaudcore/vfs_buffered_file.c
index 285bfb3..f34a0e9 100644
--- a/src/libaudcore/vfs_buffered_file.c
+++ b/src/libaudcore/vfs_buffered_file.c
@@ -50,19 +50,16 @@ buffered_file_vfs_fclose_impl(VFSFile * file)
return 0;
}
-gsize
-buffered_file_vfs_fread_impl(gpointer i_ptr,
- gsize size,
- gsize nmemb,
- VFSFile * file)
+gint64 buffered_file_vfs_fread_impl (void * i_ptr, gint64 size, gint64 nmemb,
+ VFSFile * file)
{
VFSBufferedFile *handle = (VFSBufferedFile *) file->handle;
- /* is this request within the buffered area, or should we switch to
+ /* is this request within the buffered area, or should we switch to
* an FD? --nenolod
*/
- if (handle->which == FALSE &&
- (vfs_ftell(handle->buffer)) + (size * nmemb) >
+ if (handle->which == FALSE &&
+ (vfs_ftell(handle->buffer)) + (size * nmemb) >
((VFSBuffer *) handle->buffer->handle)->size)
{
vfs_fseek(handle->fd, vfs_ftell(handle->buffer), SEEK_SET);
@@ -72,11 +69,8 @@ buffered_file_vfs_fread_impl(gpointer i_ptr,
return vfs_fread(i_ptr, size, nmemb, handle->which == TRUE ? handle->fd : handle->buffer);
}
-gsize
-buffered_file_vfs_fwrite_impl(gconstpointer i_ptr,
- gsize size,
- gsize nmemb,
- VFSFile * file)
+gint64 buffered_file_vfs_fwrite_impl (const void * i_ptr, gint64 size, gint64
+ nmemb, VFSFile * file)
{
VFSBufferedFile *handle = (VFSBufferedFile *) file->handle;
@@ -88,7 +82,7 @@ buffered_file_vfs_getc_impl(VFSFile *stream)
{
VFSBufferedFile *handle = (VFSBufferedFile *) stream->handle;
- /* is this request within the buffered area, or should we switch to
+ /* is this request within the buffered area, or should we switch to
* an FD? --nenolod
*/
if ((vfs_ftell(handle->buffer)) + 1 >
@@ -127,7 +121,7 @@ buffered_file_vfs_fseek_impl(VFSFile * file,
{
handle->which = TRUE;
vfs_fseek(handle->fd, offset, whence);
- }
+ }
break;
case SEEK_SET:
default:
diff --git a/src/libaudcore/vfs_common.c b/src/libaudcore/vfs_common.c
index a9728d7..fcee8b9 100644
--- a/src/libaudcore/vfs_common.c
+++ b/src/libaudcore/vfs_common.c
@@ -137,13 +137,13 @@ gint vfs_fprintf(VFSFile *stream, gchar const *format, ...)
* @param size Pointer to gsize variable that will hold the amount of
* read data e.g. filesize.
*/
-void
-vfs_file_get_contents(const gchar *filename, gchar **buf, gsize *size)
+void vfs_file_get_contents (const gchar * filename, guchar * * buf, gint64 *
+ size)
{
VFSFile *fd;
gsize filled_size = 0, buf_size = 4096;
- gchar *ptr;
-
+ guchar * ptr;
+
if ((fd = vfs_fopen(filename, "rb")) == NULL)
return;
@@ -171,26 +171,26 @@ vfs_file_get_contents(const gchar *filename, gchar **buf, gsize *size)
while (TRUE) {
gsize read_size = vfs_fread(ptr, 1, buf_size - filled_size, fd);
if (read_size == 0) break;
-
+
filled_size += read_size;
ptr += read_size;
-
+
if (filled_size == buf_size) {
buf_size += 4096;
-
+
*buf = g_realloc(*buf, buf_size);
-
+
if (*buf == NULL)
goto close_handle;
-
+
ptr = *buf + filled_size;
}
}
*size = filled_size;
-
+
close_handle:
- vfs_fclose(fd);
+ vfs_fclose(fd);
}
diff --git a/src/libaudgui/Makefile b/src/libaudgui/Makefile
index 2cbae8f..9c88651 100644
--- a/src/libaudgui/Makefile
+++ b/src/libaudgui/Makefile
@@ -2,7 +2,12 @@ LIB = ${LIB_PREFIX}audgui${LIB_SUFFIX}
LIB_MAJOR = 1
LIB_MINOR = 0
-SRCS = effects-menu.c \
+SRCS = confirm.c \
+ effects-menu.c \
+ infopopup.c \
+ infowin.c \
+ init.c \
+ library-store.c \
ui_gtk.c \
ui_fileopener.c \
ui_urlopener.c \
@@ -10,7 +15,9 @@ SRCS = effects-menu.c \
ui_jumptotrack_cache.c \
icons-stock.c \
ui_about.c \
- ui_credits.c
+ ui_credits.c \
+ ui_playlist_manager.c \
+ util.c
INCLUDES = libaudgui.h \
libaudgui-gtk.h
diff --git a/src/libaudgui/confirm.c b/src/libaudgui/confirm.c
new file mode 100644
index 0000000..ee64d1e
--- /dev/null
+++ b/src/libaudgui/confirm.c
@@ -0,0 +1,98 @@
+/*
+ * libaudgui/confirm.c
+ * Copyright 2010 John Lindgren
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 2 or version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+#include <audacious/i18n.h>
+#include <audacious/plugin.h>
+
+#include "libaudgui-gtk.h"
+
+static void confirm_delete_cb (GtkButton * button, void * data)
+{
+ if (GPOINTER_TO_INT (data) < aud_playlist_count ())
+ aud_playlist_delete (GPOINTER_TO_INT (data));
+}
+
+void audgui_confirm_playlist_delete (gint playlist)
+{
+ GtkWidget * window, * vbox, * hbox, * label, * button;
+ gchar * message;
+
+ if (aud_cfg->no_confirm_playlist_delete)
+ {
+ aud_playlist_delete (playlist);
+ return;
+ }
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_type_hint ((GtkWindow *) window,
+ GDK_WINDOW_TYPE_HINT_DIALOG);
+ gtk_window_set_resizable ((GtkWindow *) window, FALSE);
+ gtk_container_set_border_width ((GtkContainer *) window, 6);
+ audgui_destroy_on_escape (window);
+
+ vbox = gtk_vbox_new (FALSE, 6);
+ gtk_container_add ((GtkContainer *) window, vbox);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start ((GtkBox *) vbox, hbox, FALSE, FALSE, 0);
+
+ gtk_box_pack_start ((GtkBox *) hbox, gtk_image_new_from_stock
+ (GTK_STOCK_DIALOG_QUESTION, GTK_ICON_SIZE_DIALOG), FALSE, FALSE, 0);
+
+ message = g_strdup_printf (_("Are you sure you want to close %s? If you "
+ "do, any changes made since the playlist was exported will be lost."),
+ aud_playlist_get_title (playlist));
+ label = gtk_label_new (message);
+ g_free (message);
+ gtk_label_set_line_wrap ((GtkLabel *) label, TRUE);
+ gtk_widget_set_size_request (label, 320, -1);
+ gtk_box_pack_start ((GtkBox *) hbox, label, TRUE, FALSE, 0);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start ((GtkBox *) vbox, hbox, FALSE, FALSE, 0);
+
+ button = gtk_check_button_new_with_mnemonic (_("_Don't show this message "
+ "again"));
+ gtk_box_pack_start ((GtkBox *) hbox, button, FALSE, FALSE, 0);
+ audgui_connect_check_box (button, & aud_cfg->no_confirm_playlist_delete);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start ((GtkBox *) vbox, hbox, FALSE, FALSE, 0);
+
+ button = gtk_button_new_from_stock (GTK_STOCK_NO);
+ gtk_box_pack_end ((GtkBox *) hbox, button, FALSE, FALSE, 0);
+ g_signal_connect_swapped (button, "clicked", (GCallback)
+ gtk_widget_destroy, window);
+
+ button = gtk_button_new_from_stock (GTK_STOCK_YES);
+ gtk_box_pack_end ((GtkBox *) hbox, button, FALSE, FALSE, 0);
+#if GTK_CHECK_VERSION (2, 18, 0)
+ gtk_widget_set_can_default (button, TRUE);
+#endif
+ gtk_widget_grab_default (button);
+ gtk_widget_grab_focus (button);
+ g_signal_connect ((GObject *) button, "clicked", (GCallback)
+ confirm_delete_cb, GINT_TO_POINTER (playlist));
+ g_signal_connect_swapped ((GObject *) button, "clicked", (GCallback)
+ gtk_widget_destroy, window);
+
+ gtk_widget_show_all (window);
+}
diff --git a/src/libaudgui/infopopup.c b/src/libaudgui/infopopup.c
new file mode 100644
index 0000000..b045d4c
--- /dev/null
+++ b/src/libaudgui/infopopup.c
@@ -0,0 +1,428 @@
+/*
+ * libaudgui/infopopup.c
+ * Copyright 2006 William Pitcock, Tony Vroon, George Averill, Giacomo Lozito,
+ * Derek Pomery and Yoshiki Yazawa.
+ * Copyright 2010 John Lindgren
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 2 or version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+#include <gtk/gtk.h>
+#include <string.h>
+
+#include <audacious/i18n.h>
+#include <audacious/plugin.h>
+
+#include "libaudgui.h"
+#include "libaudgui-gtk.h"
+
+#define DEFAULT_ARTWORK DATA_DIR "/images/audio.png"
+
+static GtkWidget * infopopup = NULL;
+
+static void infopopup_entry_set_text (const gchar * entry_name, const gchar *
+ text)
+{
+ GtkWidget * widget = g_object_get_data ((GObject *) infopopup, entry_name);
+
+ g_return_if_fail (widget != NULL);
+ gtk_label_set_text ((GtkLabel *) widget, text);
+}
+
+static void infopopup_entry_set_image (const gchar * entry_name, const gchar *
+ text)
+{
+ GtkWidget * widget = g_object_get_data ((GObject *) infopopup, entry_name);
+ GdkPixbuf * pixbuf;
+ gint width, height;
+ gfloat aspect;
+
+ pixbuf = gdk_pixbuf_new_from_file (text, NULL);
+ g_return_if_fail (pixbuf != NULL);
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+
+ if (strcmp (DEFAULT_ARTWORK, text))
+ {
+ GdkPixbuf * pixbuf2;
+
+ aspect = height / (gfloat) width;
+
+ if (aspect > 1)
+ {
+ height = aud_cfg->filepopup_pixelsize * aspect;
+ width = aud_cfg->filepopup_pixelsize;
+ }
+ else
+ {
+ height = aud_cfg->filepopup_pixelsize;
+ width = aud_cfg->filepopup_pixelsize / aspect;
+ }
+
+ pixbuf2 = gdk_pixbuf_scale_simple (pixbuf, width, height,
+ GDK_INTERP_BILINEAR);
+ g_object_unref (pixbuf);
+ pixbuf = pixbuf2;
+ }
+
+ gtk_image_set_from_pixbuf ((GtkImage *) widget, pixbuf);
+ g_object_unref (pixbuf);
+}
+
+static gboolean infopopup_progress_cb (void * unused)
+{
+ GtkWidget * progressbar = g_object_get_data ((GObject *) infopopup,
+ "progressbar");
+ gchar * tooltip_file = g_object_get_data ((GObject *) infopopup, "file");
+ gint length = GPOINTER_TO_INT (g_object_get_data ((GObject *) infopopup,
+ "length"));
+ gint playlist, entry, time;
+ const gchar * filename;
+ gchar * progress_time;
+
+ g_return_val_if_fail (tooltip_file != NULL, FALSE);
+ g_return_val_if_fail (length > 0, FALSE);
+
+ if (! aud_cfg->filepopup_showprogressbar || ! audacious_drct_get_playing ())
+ goto HIDE;
+
+ playlist = aud_playlist_get_playing ();
+
+ if (playlist == -1)
+ goto HIDE;
+
+ entry = aud_playlist_get_position (playlist);
+
+ if (entry == -1)
+ goto HIDE;
+
+ filename = aud_playlist_entry_get_filename (playlist, entry);
+
+ if (strcmp (filename, tooltip_file))
+ goto HIDE;
+
+ time = audacious_drct_get_time ();
+ gtk_progress_bar_set_fraction ((GtkProgressBar *) progressbar, time /
+ (gfloat) length);
+ progress_time = g_strdup_printf ("%d:%02d", time / 60000, (time / 1000) % 60);
+ gtk_progress_bar_set_text ((GtkProgressBar *) progressbar, progress_time);
+ g_free (progress_time);
+
+ gtk_widget_show (progressbar);
+ return TRUE;
+
+HIDE:
+ /* tooltip opened, but song is not the same, or playback is stopped */
+ gtk_widget_hide (progressbar);
+ return TRUE;
+}
+
+static void infopopup_progress_init (void)
+{
+ g_object_set_data ((GObject *) infopopup, "progress_sid", GINT_TO_POINTER
+ (0));
+}
+
+static void infopopup_progress_start (void)
+{
+ gint sid = g_timeout_add (500, (GSourceFunc) infopopup_progress_cb, NULL);
+
+ g_object_set_data ((GObject *) infopopup, "progress_sid", GINT_TO_POINTER
+ (sid));
+}
+
+static void infopopup_progress_stop (void)
+{
+ gint sid = GPOINTER_TO_INT (g_object_get_data ((GObject *) infopopup,
+ "progress_sid"));
+
+ if (! sid)
+ return;
+
+ g_source_remove (sid);
+ g_object_set_data ((GObject *) infopopup, "progress_sid", GINT_TO_POINTER
+ (0));
+}
+
+static void infopopup_add_category (GtkWidget * infopopup_data_table,
+ const gchar * category, const gchar * header_data, const gchar * label_data,
+ gint position)
+{
+ GtkWidget * infopopup_data_info_header = gtk_label_new ("");
+ GtkWidget * infopopup_data_info_label = gtk_label_new ("");
+ gchar * markup;
+
+ gtk_misc_set_alignment ((GtkMisc *) infopopup_data_info_header, 0, 0.5);
+ gtk_misc_set_alignment ((GtkMisc *) infopopup_data_info_label, 0, 0.5);
+ gtk_misc_set_padding ((GtkMisc *) infopopup_data_info_header, 0, 3);
+ gtk_misc_set_padding ((GtkMisc *) infopopup_data_info_label, 0, 3);
+
+ markup = g_markup_printf_escaped ("<span style=\"italic\">%s</span>",
+ category);
+ gtk_label_set_markup ((GtkLabel *) infopopup_data_info_header, markup);
+ g_free (markup);
+
+ g_object_set_data ((GObject *) infopopup, header_data,
+ infopopup_data_info_header);
+ g_object_set_data ((GObject *) infopopup, label_data,
+ infopopup_data_info_label);
+ gtk_table_attach ((GtkTable *) infopopup_data_table,
+ infopopup_data_info_header, 0, 1, position, position + 1, GTK_FILL, 0, 0, 0);
+ gtk_table_attach ((GtkTable *) infopopup_data_table,
+ infopopup_data_info_label, 1, 2, position, position + 1, GTK_FILL, 0, 0, 0);
+}
+
+static void infopopup_create (void)
+{
+ GtkWidget * infopopup_hbox;
+ GtkWidget * infopopup_data_image;
+ GtkWidget * infopopup_data_table;
+ GtkWidget * infopopup_progress;
+
+ infopopup = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_window_set_type_hint ((GtkWindow *) infopopup,
+ GDK_WINDOW_TYPE_HINT_TOOLTIP);
+ gtk_window_set_decorated ((GtkWindow *) infopopup, FALSE);
+ gtk_container_set_border_width ((GtkContainer *) infopopup, 6);
+
+ infopopup_hbox = gtk_hbox_new (FALSE, 0);
+ gtk_container_add ((GtkContainer *) infopopup, infopopup_hbox);
+
+ infopopup_data_image = gtk_image_new ();
+ gtk_misc_set_alignment ((GtkMisc *) infopopup_data_image, 0.5, 0);
+ gtk_image_set_from_file ((GtkImage *) infopopup_data_image, DEFAULT_ARTWORK);
+
+ g_object_set_data ((GObject *) infopopup, "image_artwork",
+ infopopup_data_image);
+ g_object_set_data ((GObject *) infopopup, "last_artwork", NULL);
+ gtk_box_pack_start ((GtkBox *) infopopup_hbox, infopopup_data_image, FALSE,
+ FALSE, 0);
+
+ gtk_box_pack_start ((GtkBox *) infopopup_hbox, gtk_vseparator_new (), FALSE,
+ FALSE, 6);
+
+ infopopup_data_table = gtk_table_new (8, 2, FALSE);
+ gtk_table_set_row_spacings ((GtkTable *) infopopup_data_table, 0);
+ gtk_table_set_col_spacings ((GtkTable *) infopopup_data_table, 6);
+ gtk_box_pack_start ((GtkBox *) infopopup_hbox, infopopup_data_table, TRUE,
+ TRUE, 0);
+
+ infopopup_add_category (infopopup_data_table, _("Title"), "header_title",
+ "label_title", 0);
+ infopopup_add_category (infopopup_data_table, _("Artist"), "header_artist",
+ "label_artist", 1);
+ infopopup_add_category (infopopup_data_table, _("Album"), "header_album",
+ "label_album", 2);
+ infopopup_add_category (infopopup_data_table, _("Genre"), "header_genre",
+ "label_genre", 3);
+ infopopup_add_category (infopopup_data_table, _("Year"), "header_year",
+ "label_year", 4);
+ infopopup_add_category (infopopup_data_table, _("Track Number"),
+ "header_tracknum", "label_tracknum", 5);
+ infopopup_add_category (infopopup_data_table, _("Track Length"),
+ "header_tracklen", "label_tracklen", 6);
+
+ gtk_table_set_row_spacing ((GtkTable *) infopopup_data_table, 6, 6);
+
+ /* track progress */
+ infopopup_progress = gtk_progress_bar_new ();
+ gtk_progress_bar_set_orientation ((GtkProgressBar *) infopopup_progress,
+ GTK_PROGRESS_LEFT_TO_RIGHT);
+ gtk_progress_bar_set_text ((GtkProgressBar *) infopopup_progress, "");
+ gtk_table_attach ((GtkTable *) infopopup_data_table, infopopup_progress, 0,
+ 2, 7, 8, GTK_FILL, 0, 0, 0);
+ g_object_set_data ((GObject *) infopopup, "file", NULL);
+ g_object_set_data ((GObject *) infopopup, "progressbar", infopopup_progress);
+ infopopup_progress_init ();
+
+ /* do not show the track progress */
+ gtk_widget_set_no_show_all (infopopup_progress, TRUE);
+ gtk_widget_show_all (infopopup_hbox);
+}
+
+#if 0
+static void infopopup_destroy (void)
+{
+ infopopup_progress_stop (infopopup);
+ g_free (g_object_get_data ((GObject *) infopopup, "last_artwork"));
+ gtk_widget_destroy (infopopup);
+}
+#endif
+
+static void infopopup_update_data (const gchar * text, const gchar * label_data,
+ const gchar * header_data)
+{
+ if (text != NULL)
+ {
+ infopopup_entry_set_text (label_data, text);
+ gtk_widget_show ((GtkWidget *) g_object_get_data ((GObject *) infopopup,
+ header_data));
+ gtk_widget_show ((GtkWidget *) g_object_get_data ((GObject *) infopopup,
+ label_data));
+ }
+ else
+ {
+ gtk_widget_hide ((GtkWidget *) g_object_get_data ((GObject *) infopopup,
+ header_data));
+ gtk_widget_hide ((GtkWidget *) g_object_get_data ((GObject *) infopopup,
+ label_data));
+ }
+}
+
+static void infopopup_clear (void)
+{
+ infopopup_progress_stop ();
+
+ infopopup_entry_set_text ("label_title", "");
+ infopopup_entry_set_text ("label_artist", "");
+ infopopup_entry_set_text ("label_album", "");
+ infopopup_entry_set_text ("label_genre", "");
+ infopopup_entry_set_text ("label_tracknum", "");
+ infopopup_entry_set_text ("label_year", "");
+ infopopup_entry_set_text ("label_tracklen", "");
+
+ gtk_window_resize ((GtkWindow *) infopopup, 1, 1);
+}
+
+static void infopopup_show (const gchar * filename, Tuple * tuple, const gchar *
+ title)
+{
+ gint x, y, h, w;
+ gchar * last_artwork;
+ gint length, value;
+ gchar * tmp, * markup;
+
+ if (infopopup == NULL)
+ infopopup_create ();
+ else
+ infopopup_clear ();
+
+ g_free (g_object_get_data ((GObject *) infopopup, "file"));
+ g_object_set_data ((GObject *) infopopup, "file", g_strdup (filename));
+
+ markup = g_markup_printf_escaped ("<span style=\"italic\">%s</span>",
+ _("Title"));
+ gtk_label_set_markup ((GtkLabel *) g_object_get_data ((GObject *) infopopup,
+ "header_title"), markup);
+ g_free (markup);
+ infopopup_entry_set_text ("label_title", title);
+
+ infopopup_update_data (tuple_get_string (tuple, FIELD_ARTIST, NULL),
+ "label_artist", "header_artist");
+ infopopup_update_data (tuple_get_string (tuple, FIELD_ALBUM, NULL),
+ "label_album", "header_album");
+ infopopup_update_data (tuple_get_string (tuple, FIELD_GENRE, NULL),
+ "label_genre", "header_genre");
+
+ length = tuple_get_int (tuple, FIELD_LENGTH, NULL);
+ tmp = (length > 0) ? g_strdup_printf ("%d:%02d", length / 60000, length /
+ 1000 % 60) : NULL;
+ infopopup_update_data (tmp, "label_tracklen", "header_tracklen");
+ g_free (tmp);
+
+ g_object_set_data ((GObject *) infopopup, "length" , GINT_TO_POINTER (length));
+
+ value = tuple_get_int (tuple, FIELD_YEAR, NULL);
+ tmp = (value > 0) ? g_strdup_printf ("%d", value) : NULL;
+ infopopup_update_data (tmp, "label_year", "header_year");
+ g_free (tmp);
+
+ value = tuple_get_int (tuple, FIELD_TRACK_NUMBER, NULL);
+ tmp = (value > 0) ? g_strdup_printf ("%d", value) : NULL;
+ infopopup_update_data (tmp, "label_tracknum", "header_tracknum");
+ g_free (tmp);
+
+ last_artwork = g_object_get_data ((GObject *) infopopup, "last_artwork");
+ tmp = aud_get_associated_image_file (filename);
+
+ if (tmp == NULL)
+ tmp = g_strdup (DEFAULT_ARTWORK);
+
+ if (last_artwork == NULL || strcmp (tmp, last_artwork))
+ {
+ infopopup_entry_set_image ("image_artwork", tmp);
+ g_free (last_artwork);
+ g_object_set_data ((GObject *) infopopup, "last_artwork", tmp);
+ }
+ else
+ g_free (tmp);
+
+ /* start a timer that updates a progress bar if the tooltip
+ is shown for the song that is being currently played */
+ if (length > 0)
+ {
+ infopopup_progress_start ();
+ /* immediately run the callback once to update progressbar status */
+ infopopup_progress_cb (NULL);
+ }
+
+ gdk_window_get_pointer (gdk_get_default_root_window (), & x, & y, NULL);
+ gtk_window_get_size ((GtkWindow *) infopopup, & w, & h);
+
+ /* If we show the popup right under the cursor, the underlying window gets
+ * a "leave-notify-event" and immediately hides the popup again. So, we
+ * offset the popup slightly. */
+ if (x + w > gdk_screen_width ())
+ x -= w + 3;
+ else
+ x += 3;
+
+ if (y + h > gdk_screen_height ())
+ y -= h + 3;
+ else
+ y += 3;
+
+ gtk_window_move ((GtkWindow *) infopopup, x, y);
+ gtk_widget_show (infopopup);
+}
+
+void audgui_infopopup_show (gint playlist, gint entry)
+{
+ const gchar * filename = aud_playlist_entry_get_filename (playlist, entry);
+ Tuple * tuple = (Tuple *) aud_playlist_entry_get_tuple (playlist, entry);
+
+ g_return_if_fail (filename != NULL);
+
+ if (tuple == NULL) /* FIXME: show an error popup if this happens */
+ return;
+
+ infopopup_show (filename, tuple, aud_playlist_entry_get_title (playlist,
+ entry));
+}
+
+void audgui_infopopup_show_current (void)
+{
+ gint playlist = aud_playlist_get_playing ();
+ gint position;
+
+ if (playlist == -1)
+ playlist = aud_playlist_get_active ();
+
+ position = aud_playlist_get_position (playlist);
+
+ if (position == -1)
+ return;
+
+ audgui_infopopup_show (playlist, position);
+}
+
+void audgui_infopopup_hide (void)
+{
+ infopopup_progress_stop ();
+ gtk_widget_hide (infopopup);
+}
diff --git a/src/libaudgui/infowin.c b/src/libaudgui/infowin.c
new file mode 100644
index 0000000..ef58480
--- /dev/null
+++ b/src/libaudgui/infowin.c
@@ -0,0 +1,912 @@
+/*
+ * libaudgui/infowin.c
+ * Copyright 2006 William Pitcock, Tony Vroon, George Averill, Giacomo Lozito,
+ * Derek Pomery and Yoshiki Yazawa.
+ * Copyright 2008 Eugene Zagidullin
+ * Copyright 2010 John Lindgren
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 2 or version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+#include <gtk/gtk.h>
+#include <stdarg.h>
+
+#include <audacious/i18n.h>
+#include <audacious/plugin.h>
+#include <libaudcore/audstrings.h>
+
+#include "libaudgui.h"
+#include "libaudgui-gtk.h"
+
+#define STATUS_TIMEOUT 3000
+
+static GtkWidget * infowin = NULL;
+
+static GtkWidget * location_text;
+static GtkWidget * entry_title;
+static GtkWidget * entry_artist;
+static GtkWidget * entry_album;
+static GtkWidget * entry_comment;
+static GtkWidget * entry_year;
+static GtkWidget * entry_track;
+static GtkWidget * entry_genre;
+
+static GtkWidget * image_artwork;
+
+static GtkWidget * image_fileicon;
+static GtkWidget * label_format_name;
+static GtkWidget * label_quality;
+static GtkWidget * label_bitrate;
+static GtkWidget * btn_apply;
+static GtkWidget * label_mini_status;
+static GtkWidget * arrow_rawdata;
+static GtkWidget * treeview_rawdata;
+
+enum
+{
+ RAWDATA_KEY,
+ RAWDATA_VALUE,
+ RAWDATA_N_COLS
+};
+
+static gchar * current_file = NULL;
+static InputPlugin * current_decoder = NULL;
+static gboolean can_write = FALSE, something_changed = FALSE;
+
+static const gchar * genre_table[] =
+{
+ N_("Blues"), N_("Classic Rock"), N_("Country"), N_("Dance"),
+ N_("Disco"), N_("Funk"), N_("Grunge"), N_("Hip-Hop"),
+ N_("Jazz"), N_("Metal"), N_("New Age"), N_("Oldies"),
+ N_("Other"), N_("Pop"), N_("R&B"), N_("Rap"), N_("Reggae"),
+ N_("Rock"), N_("Techno"), N_("Industrial"), N_("Alternative"),
+ N_("Ska"), N_("Death Metal"), N_("Pranks"), N_("Soundtrack"),
+ N_("Euro-Techno"), N_("Ambient"), N_("Trip-Hop"), N_("Vocal"),
+ N_("Jazz+Funk"), N_("Fusion"), N_("Trance"), N_("Classical"),
+ N_("Instrumental"), N_("Acid"), N_("House"), N_("Game"),
+ N_("Sound Clip"), N_("Gospel"), N_("Noise"), N_("AlternRock"),
+ N_("Bass"), N_("Soul"), N_("Punk"), N_("Space"),
+ N_("Meditative"), N_("Instrumental Pop"),
+ N_("Instrumental Rock"), N_("Ethnic"), N_("Gothic"),
+ N_("Darkwave"), N_("Techno-Industrial"), N_("Electronic"),
+ N_("Pop-Folk"), N_("Eurodance"), N_("Dream"),
+ N_("Southern Rock"), N_("Comedy"), N_("Cult"),
+ N_("Gangsta Rap"), N_("Top 40"), N_("Christian Rap"),
+ N_("Pop/Funk"), N_("Jungle"), N_("Native American"),
+ N_("Cabaret"), N_("New Wave"), N_("Psychedelic"), N_("Rave"),
+ N_("Showtunes"), N_("Trailer"), N_("Lo-Fi"), N_("Tribal"),
+ N_("Acid Punk"), N_("Acid Jazz"), N_("Polka"), N_("Retro"),
+ N_("Musical"), N_("Rock & Roll"), N_("Hard Rock"), N_("Folk"),
+ N_("Folk/Rock"), N_("National Folk"), N_("Swing"),
+ N_("Fast-Fusion"), N_("Bebob"), N_("Latin"), N_("Revival"),
+ N_("Celtic"), N_("Bluegrass"), N_("Avantgarde"),
+ N_("Gothic Rock"), N_("Progressive Rock"),
+ N_("Psychedelic Rock"), N_("Symphonic Rock"), N_("Slow Rock"),
+ N_("Big Band"), N_("Chorus"), N_("Easy Listening"),
+ N_("Acoustic"), N_("Humour"), N_("Speech"), N_("Chanson"),
+ N_("Opera"), N_("Chamber Music"), N_("Sonata"), N_("Symphony"),
+ N_("Booty Bass"), N_("Primus"), N_("Porn Groove"),
+ N_("Satire"), N_("Slow Jam"), N_("Club"), N_("Tango"),
+ N_("Samba"), N_("Folklore"), N_("Ballad"), N_("Power Ballad"),
+ N_("Rhythmic Soul"), N_("Freestyle"), N_("Duet"),
+ N_("Punk Rock"), N_("Drum Solo"), N_("A Cappella"),
+ N_("Euro-House"), N_("Dance Hall"), N_("Goa"),
+ N_("Drum & Bass"), N_("Club-House"), N_("Hardcore"),
+ N_("Terror"), N_("Indie"), N_("BritPop"), N_("Negerpunk"),
+ N_("Polsk Punk"), N_("Beat"), N_("Christian Gangsta Rap"),
+ N_("Heavy Metal"), N_("Black Metal"), N_("Crossover"),
+ N_("Contemporary Christian"), N_("Christian Rock"),
+ N_("Merengue"), N_("Salsa"), N_("Thrash Metal"),
+ N_("Anime"), N_("JPop"), N_("Synthpop")
+};
+
+static GList * genre_list = NULL;
+
+static void set_entry_str_from_field (GtkWidget * widget, Tuple * tuple,
+ gint fieldn, gboolean editable)
+{
+ const gchar * text = tuple_get_string (tuple, fieldn, NULL);
+
+ gtk_entry_set_text ((GtkEntry *) widget, text != NULL ? text : "");
+ gtk_editable_set_editable ((GtkEditable *) widget, editable);
+}
+
+static void set_entry_int_from_field (GtkWidget * widget, Tuple * tuple, gint
+ fieldn, gboolean editable)
+{
+ gchar scratch[32];
+
+ if (tuple_get_value_type (tuple, fieldn, NULL) == TUPLE_INT)
+ snprintf (scratch, sizeof scratch, "%d", tuple_get_int (tuple, fieldn,
+ NULL));
+ else
+ scratch[0] = 0;
+
+ gtk_entry_set_text ((GtkEntry *) widget, scratch);
+ gtk_editable_set_editable ((GtkEditable *) widget, editable);
+}
+
+static void set_field_str_from_entry (Tuple * tuple, gint fieldn, GtkWidget *
+ widget)
+{
+ const gchar * text = gtk_entry_get_text ((GtkEntry *) widget);
+
+ if (text[0])
+ tuple_associate_string (tuple, fieldn, NULL, text);
+ else
+ tuple_disassociate (tuple, fieldn, NULL);
+}
+
+static void set_field_int_from_entry (Tuple * tuple, gint fieldn, GtkWidget *
+ widget)
+{
+ const gchar * text = gtk_entry_get_text ((GtkEntry *) widget);
+
+ if (text[0])
+ tuple_associate_int (tuple, fieldn, NULL, atoi (text));
+ else
+ tuple_disassociate (tuple, fieldn, NULL);
+}
+
+static void infowin_label_set_text (GtkWidget * widget, const gchar * text)
+{
+ gchar * tmp;
+
+ if (text != NULL)
+ {
+ tmp = g_strdup_printf("<span size=\"small\">%s</span>", text);
+ gtk_label_set_text ((GtkLabel *) widget, tmp);
+ g_free (tmp);
+ }
+ else
+ gtk_label_set_text ((GtkLabel *) widget,
+ _("<span size=\"small\">n/a</span>"));
+
+ gtk_label_set_use_markup ((GtkLabel *) widget, TRUE);
+}
+
+static void infowin_entry_set_image (GtkWidget * widget, const char * text)
+{
+ GdkPixbuf * pixbuf;
+
+ pixbuf = gdk_pixbuf_new_from_file (text, NULL);
+ g_return_if_fail (pixbuf != NULL);
+
+ if (strcmp (DATA_DIR "/images/audio.png", text))
+ audgui_pixbuf_scale_within (& pixbuf, aud_cfg->filepopup_pixelsize);
+
+ gtk_image_set_from_pixbuf ((GtkImage *) widget, pixbuf);
+ g_object_unref (pixbuf);
+}
+
+static void clear_infowin (void)
+{
+ gtk_entry_set_text ((GtkEntry *) entry_title, "");
+ gtk_entry_set_text ((GtkEntry *) entry_artist, "");
+ gtk_entry_set_text ((GtkEntry *) entry_album, "");
+ gtk_entry_set_text ((GtkEntry *) entry_comment, "");
+ gtk_entry_set_text ((GtkEntry *) gtk_bin_get_child ((GtkBin *) entry_genre),
+ "");
+ gtk_entry_set_text ((GtkEntry *) entry_year, "");
+ gtk_entry_set_text ((GtkEntry *) entry_track, "");
+
+ infowin_label_set_text (label_format_name, NULL);
+ infowin_label_set_text (label_quality, NULL);
+ infowin_label_set_text (label_bitrate, NULL);
+
+ gtk_label_set_text ((GtkLabel *) label_mini_status,
+ "<span size=\"small\"></span>");
+ gtk_label_set_use_markup ((GtkLabel *) label_mini_status, TRUE);
+
+ g_free (current_file);
+ current_file = NULL;
+ current_decoder = NULL;
+
+ something_changed = FALSE;
+ can_write = FALSE;
+ gtk_widget_set_sensitive (btn_apply, FALSE);
+
+ infowin_entry_set_image (image_artwork, DATA_DIR "/images/audio.png");
+}
+
+static void entry_changed (GtkEditable * editable, void * unused)
+{
+ if (! something_changed && can_write)
+ {
+ something_changed = TRUE;
+ gtk_widget_set_sensitive (btn_apply, TRUE);
+ }
+}
+
+static gboolean ministatus_timeout_proc (void * data)
+{
+ GtkLabel * status = data;
+
+ gtk_label_set_text (status, "<span size=\"small\"></span>");
+ gtk_label_set_use_markup (status, TRUE);
+
+ return FALSE;
+}
+
+static void ministatus_display_message (const gchar * text)
+{
+ gchar * tmp = g_strdup_printf ("<span size=\"small\">%s</span>", text);
+
+ gtk_label_set_text ((GtkLabel *) label_mini_status, tmp);
+ gtk_label_set_use_markup ((GtkLabel *) label_mini_status, TRUE);
+ g_free (tmp);
+
+ g_timeout_add (STATUS_TIMEOUT, (GSourceFunc) ministatus_timeout_proc,
+ label_mini_status);
+}
+
+static void infowin_update_tuple (void * unused)
+{
+ Tuple * tuple = tuple_new_from_filename (current_file);
+
+ set_field_str_from_entry (tuple, FIELD_TITLE, entry_title);
+ set_field_str_from_entry (tuple, FIELD_ARTIST, entry_artist);
+ set_field_str_from_entry (tuple, FIELD_ALBUM, entry_album);
+ set_field_str_from_entry (tuple, FIELD_COMMENT, entry_comment);
+ set_field_str_from_entry (tuple, FIELD_GENRE, gtk_bin_get_child ((GtkBin *)
+ entry_genre));
+ set_field_int_from_entry (tuple, FIELD_YEAR, entry_year);
+ set_field_int_from_entry (tuple, FIELD_TRACK_NUMBER, entry_track);
+
+ if (aud_file_write_tuple (current_file, current_decoder, tuple))
+ {
+ ministatus_display_message (_("Metadata updated successfully"));
+ something_changed = FALSE;
+ gtk_widget_set_sensitive (btn_apply, FALSE);
+ }
+ else
+ ministatus_display_message (_("Metadata updating failed"));
+
+ mowgli_object_unref (tuple);
+}
+
+/**
+ * Looks up an icon from a NULL-terminated list of icon names.
+ *
+ * size: the requested size
+ * name: the default name
+ * ... : a NULL-terminated list of alternates
+ */
+static GdkPixbuf * themed_icon_lookup (gint size, const gchar * name, ...)
+{
+ GtkIconTheme * icon_theme;
+ GdkPixbuf * pixbuf;
+ const gchar * n;
+ va_list par;
+
+ icon_theme = gtk_icon_theme_get_default ();
+ pixbuf = gtk_icon_theme_load_icon (icon_theme, name, size, 0, NULL);
+
+ if (pixbuf != NULL)
+ return pixbuf;
+
+ /* fallback */
+ va_start (par, name);
+
+ while ((n = va_arg (par, const gchar *)) != NULL)
+ {
+ pixbuf = gtk_icon_theme_load_icon (icon_theme, n, size, 0, NULL);
+
+ if (pixbuf)
+ {
+ va_end (par);
+ return pixbuf;
+ }
+ }
+
+ va_end (par);
+ return NULL;
+}
+
+/**
+ * Intelligently looks up an icon for a mimetype. Supports
+ * HIDEOUSLY BROKEN gnome icon naming scheme too.
+ *
+ * size : the requested size
+ * mime_type: the mime type.
+ */
+static GdkPixbuf * mime_icon_lookup (gint size, const gchar * mime_type)
+{
+ gchar * mime_as_is; /* audio-x-mp3 */
+ gchar * mime_gnome; /* gnome-mime-audio-x-mp3 */
+ gchar * mime_generic; /* audio-x-generic */
+ gchar * mime_gnome_generic; /* gnome-mime-audio */
+ GdkPixbuf * icon = NULL;
+ gchar * * s = g_strsplit (mime_type, "/", 2);
+
+ if (s[1] != NULL)
+ {
+ mime_as_is = g_strdup_printf ("%s-%s", s[0], s[1]);
+ mime_gnome = g_strdup_printf ("gnome-mime-%s-%s", s[0], s[1]);
+ mime_generic = g_strdup_printf ("%s-x-generic", s[0]);
+ mime_gnome_generic = g_strdup_printf ("gnome-mime-%s", s[0]);
+
+ icon = themed_icon_lookup (size, mime_as_is, mime_gnome, mime_generic,
+ mime_gnome_generic, s[0], NULL); /* s[0] is category */
+
+ g_free (mime_gnome_generic);
+ g_free (mime_generic);
+ g_free (mime_gnome);
+ g_free (mime_as_is);
+ }
+
+ g_strfreev (s);
+ return icon;
+}
+
+void create_infowin (void)
+{
+ GtkWidget * hbox;
+ GtkWidget * hbox_status_and_bbox;
+ GtkWidget * vbox0;
+ GtkWidget * vbox1;
+ GtkWidget * vbox2;
+ GtkWidget * vbox3;
+ GtkWidget * label_title;
+ GtkWidget * label_artist;
+ GtkWidget * label_album;
+ GtkWidget * label_comment;
+ GtkWidget * label_genre;
+ GtkWidget * label_year;
+ GtkWidget * label_track;
+ GtkWidget * label_location;
+ GtkWidget * label_general;
+ GtkWidget * label_format;
+ GtkWidget * label_quality_label;
+ GtkWidget * label_bitrate_label;
+ GtkWidget * codec_hbox;
+ GtkWidget * codec_table;
+ GtkWidget * table1;
+ GtkWidget * bbox_close;
+ GtkWidget * btn_close;
+ GtkWidget * alignment;
+ GtkWidget * separator;
+ GtkWidget * scrolledwindow;
+ GtkTreeViewColumn * column;
+ GtkCellRenderer * renderer;
+ gint i;
+
+ infowin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_container_set_border_width ((GtkContainer *) infowin, 6);
+ gtk_window_set_title ((GtkWindow *) infowin, _("Track Information"));
+ gtk_window_set_type_hint ((GtkWindow *) infowin,
+ GDK_WINDOW_TYPE_HINT_DIALOG);
+
+ vbox0 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add ((GtkContainer *) infowin, vbox0);
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start ((GtkBox *) vbox0, hbox, TRUE, TRUE, 0);
+
+ image_artwork = gtk_image_new ();
+ gtk_box_pack_start ((GtkBox *) hbox, image_artwork, FALSE, FALSE, 0);
+ gtk_misc_set_alignment ((GtkMisc *) image_artwork, 0.5, 0);
+ gtk_image_set_from_file ((GtkImage *) image_artwork, DATA_DIR
+ "/images/audio.png");
+ separator = gtk_vseparator_new ();
+ gtk_box_pack_start ((GtkBox *) hbox, separator, FALSE, FALSE, 0);
+
+ vbox1 = gtk_vbox_new (FALSE, 0);
+ gtk_box_pack_start ((GtkBox *) hbox, vbox1, TRUE, TRUE, 0);
+
+ alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
+ gtk_box_pack_start ((GtkBox *) vbox1, alignment, TRUE, TRUE, 0);
+
+ vbox2 = gtk_vbox_new (FALSE, 0);
+ gtk_container_add ((GtkContainer *) alignment, vbox2);
+
+ alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
+ gtk_box_pack_start ((GtkBox *) vbox1, alignment, TRUE, TRUE, 0);
+
+ vbox3 = gtk_vbox_new(FALSE, 0);
+ gtk_container_add ((GtkContainer *) alignment, vbox3);
+
+ label_general = gtk_label_new (_("<span size=\"small\">General</span>"));
+ gtk_box_pack_start ((GtkBox *) vbox2, label_general, FALSE, FALSE, 0);
+ gtk_label_set_use_markup ((GtkLabel *) label_general, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_general, 0, 0.5);
+
+ alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
+ gtk_alignment_set_padding ((GtkAlignment *) alignment, 6, 6, 0, 0);
+ gtk_box_pack_start ((GtkBox *) vbox2, alignment, FALSE, FALSE, 0);
+
+ codec_hbox = gtk_hbox_new (FALSE, 6);
+ gtk_container_add ((GtkContainer *) alignment, codec_hbox);
+
+ image_fileicon = gtk_image_new_from_stock (GTK_STOCK_MISSING_IMAGE,
+ GTK_ICON_SIZE_DIALOG);
+ gtk_box_pack_start ((GtkBox *) codec_hbox, image_fileicon, FALSE, FALSE, 0);
+
+ codec_table = gtk_table_new(3, 2, FALSE);
+ gtk_table_set_row_spacings ((GtkTable *) codec_table, 6);
+ gtk_table_set_col_spacings ((GtkTable *) codec_table, 12);
+ gtk_box_pack_start ((GtkBox *) codec_hbox, codec_table, FALSE, FALSE, 0);
+
+ label_format = gtk_label_new (_("<span size=\"small\">Format:</span>"));
+ gtk_label_set_use_markup ((GtkLabel *) label_format, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_format, 0, 0.5);
+ label_quality_label = gtk_label_new
+ (_("<span size=\"small\">Quality:</span>"));
+ gtk_label_set_use_markup ((GtkLabel *) label_quality_label, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_quality_label, 0, 0.5);
+ label_bitrate_label = gtk_label_new (_("<span size=\"small\">Bitrate:</span>"));
+ gtk_label_set_use_markup ((GtkLabel *) label_bitrate_label, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_bitrate_label, 0, 0.5);
+
+ label_format_name = gtk_label_new (_("<span size=\"small\">n/a</span>"));
+ gtk_label_set_use_markup ((GtkLabel *) label_format_name, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_format_name, 0, 0.5);
+ label_quality = gtk_label_new (_("<span size=\"small\">n/a</span>"));
+ gtk_label_set_use_markup ((GtkLabel *) label_quality, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_quality, 0, 0.5);
+ label_bitrate = gtk_label_new (_("<span size=\"small\">n/a</span>"));
+ gtk_label_set_use_markup ((GtkLabel *) label_bitrate, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_bitrate, 0, 0.5);
+
+ gtk_table_attach ((GtkTable *) codec_table, label_format, 0, 1, 0, 1,
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
+ gtk_table_attach ((GtkTable *) codec_table, label_format_name, 1, 2, 0, 1,
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
+ gtk_table_attach ((GtkTable *) codec_table, label_quality_label, 0, 1, 1, 2,
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
+ gtk_table_attach ((GtkTable *) codec_table, label_quality, 1, 2, 1, 2,
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
+ gtk_table_attach ((GtkTable *) codec_table, label_bitrate_label, 0, 1, 2, 3,
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
+ gtk_table_attach ((GtkTable *) codec_table, label_bitrate, 1, 2, 2, 3,
+ GTK_EXPAND | GTK_FILL, 0, 0, 0);
+
+ label_title = gtk_label_new (_("<span size=\"small\">Title</span>"));
+ gtk_box_pack_start ((GtkBox *) vbox2, label_title, FALSE, FALSE, 0);
+ gtk_label_set_use_markup ((GtkLabel *) label_title, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_title, 0, 0);
+
+ alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
+ gtk_box_pack_start ((GtkBox *) vbox2, alignment, FALSE, FALSE, 0);
+ gtk_alignment_set_padding ((GtkAlignment *) alignment, 0, 6, 0, 0);
+ entry_title = gtk_entry_new ();
+ gtk_container_add ((GtkContainer *) alignment, entry_title);
+ g_signal_connect (entry_title, "changed", (GCallback) entry_changed, NULL);
+
+ label_artist = gtk_label_new (_("<span size=\"small\">Artist</span>"));
+ gtk_box_pack_start ((GtkBox *) vbox2, label_artist, FALSE, FALSE, 0);
+ gtk_label_set_use_markup ((GtkLabel *) label_artist, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_artist, 0, 0.5);
+
+ alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
+ gtk_box_pack_start ((GtkBox *) vbox2, alignment, FALSE, FALSE, 0);
+ gtk_alignment_set_padding ((GtkAlignment *) alignment, 0, 6, 0, 0);
+ entry_artist = gtk_entry_new ();
+ gtk_container_add ((GtkContainer *) alignment, entry_artist);
+ g_signal_connect (entry_artist, "changed", (GCallback) entry_changed, NULL);
+
+ label_album = gtk_label_new (_("<span size=\"small\">Album</span>"));
+ gtk_box_pack_start ((GtkBox *) vbox2, label_album, FALSE, FALSE, 0);
+ gtk_label_set_use_markup ((GtkLabel *) label_album, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_album, 0, 0.5);
+
+ alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
+ gtk_box_pack_start ((GtkBox *) vbox2, alignment, FALSE, FALSE, 0);
+ gtk_alignment_set_padding ((GtkAlignment *) alignment, 0, 6, 0, 0);
+ entry_album = gtk_entry_new ();
+ gtk_container_add ((GtkContainer *) alignment, entry_album);
+ g_signal_connect (entry_album, "changed", (GCallback) entry_changed, NULL);
+
+ label_comment = gtk_label_new (_("<span size=\"small\">Comment</span>"));
+ gtk_box_pack_start ((GtkBox *) vbox2, label_comment, FALSE, FALSE, 0);
+ gtk_label_set_use_markup ((GtkLabel *) label_comment, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_comment, 0, 0.5);
+
+ alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
+ gtk_box_pack_start ((GtkBox *) vbox2, alignment, FALSE, FALSE, 0);
+ gtk_alignment_set_padding ((GtkAlignment *) alignment, 0, 6, 0, 0);
+ entry_comment = gtk_entry_new ();
+ gtk_container_add ((GtkContainer *) alignment, entry_comment);
+ g_signal_connect (entry_comment, "changed", (GCallback) entry_changed, NULL);
+
+ label_genre = gtk_label_new (_("<span size=\"small\">Genre</span>"));
+ gtk_box_pack_start ((GtkBox *) vbox2, label_genre, FALSE, FALSE, 0);
+ gtk_label_set_use_markup ((GtkLabel *) label_genre, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_genre, 0, 0.5);
+
+ alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
+ gtk_box_pack_start ((GtkBox *) vbox2, alignment, FALSE, FALSE, 0);
+ gtk_alignment_set_padding ((GtkAlignment *) alignment, 0, 6, 0, 0);
+ entry_genre = gtk_combo_box_entry_new_text ();
+
+ if (genre_list == NULL)
+ {
+ GList * iter;
+
+ for (i = 0; i < G_N_ELEMENTS (genre_table); i ++)
+ genre_list = g_list_prepend (genre_list, _(genre_table[i]));
+
+ genre_list = g_list_sort (genre_list, (GCompareFunc) g_utf8_collate);
+
+ for (iter = genre_list; iter != NULL; iter = iter->next)
+ gtk_combo_box_append_text ((GtkComboBox *) entry_genre, iter->data);
+ }
+
+ gtk_container_add ((GtkContainer *) alignment, entry_genre);
+ g_signal_connect (entry_genre, "changed", (GCallback) entry_changed, NULL);
+
+ alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
+ gtk_box_pack_start ((GtkBox *) vbox2, alignment, FALSE, FALSE, 0);
+ gtk_alignment_set_padding ((GtkAlignment *) alignment, 0, 6, 0, 0);
+ table1 = gtk_table_new (2, 2, FALSE);
+ gtk_container_add ((GtkContainer *) alignment, table1);
+ gtk_table_set_col_spacings ((GtkTable *) table1, 6);
+
+ label_year = gtk_label_new (_("<span size=\"small\">Year</span>"));
+ gtk_table_attach ((GtkTable *) table1, label_year, 0, 1, 0, 1, GTK_FILL, 0,
+ 0, 0);
+ gtk_label_set_use_markup ((GtkLabel *) label_year, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_year, 0, 0.5);
+
+ entry_year = gtk_entry_new ();
+ gtk_table_attach ((GtkTable *) table1, entry_year, 0, 1, 1, 2, GTK_EXPAND |
+ GTK_FILL, 0, 0, 0);
+ g_signal_connect (entry_year, "changed", (GCallback) entry_changed, NULL);
+
+ label_track = gtk_label_new (_("<span size=\"small\">Track Number</span>"));
+ gtk_table_attach ((GtkTable *) table1, label_track, 1, 2, 0, 1, GTK_FILL, 0,
+ 0, 0);
+ gtk_label_set_use_markup ((GtkLabel *) label_track, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_track, 0, 0.5);
+
+ entry_track = gtk_entry_new ();
+ gtk_table_attach ((GtkTable *) table1, entry_track, 1, 2, 1, 2, GTK_EXPAND |
+ GTK_FILL, 0, 0, 0);
+ g_signal_connect (entry_track, "changed", (GCallback) entry_changed, NULL);
+
+ label_location = gtk_label_new (_("<span size=\"small\">Location</span>"));
+ gtk_box_pack_start ((GtkBox *) vbox2, label_location, FALSE, FALSE, 0);
+ gtk_label_set_use_markup ((GtkLabel *) label_location, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_location, 0, 0.5);
+
+ alignment = gtk_alignment_new (0, 0, 0, 0);
+ gtk_alignment_set_padding ((GtkAlignment *) alignment, 3, 6, 25, 0);
+ gtk_box_pack_start ((GtkBox *) vbox2, alignment, FALSE, FALSE, 0);
+
+ location_text = gtk_label_new ("");
+ gtk_widget_set_size_request (location_text, 375, -1);
+ gtk_label_set_line_wrap ((GtkLabel *) location_text, TRUE);
+#if GTK_CHECK_VERSION (2, 10, 0)
+ gtk_label_set_line_wrap_mode ((GtkLabel *) location_text,
+ PANGO_WRAP_WORD_CHAR);
+#endif
+ gtk_label_set_selectable ((GtkLabel *) location_text, TRUE);
+ gtk_container_add ((GtkContainer *) alignment, location_text);
+
+ alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
+ hbox = gtk_hbox_new (FALSE, 0);
+ gtk_container_add ((GtkContainer *) alignment, hbox);
+ gtk_box_pack_start ((GtkBox *) vbox3, alignment, TRUE, TRUE, 0);
+
+ alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
+ gtk_alignment_set_padding ((GtkAlignment *) (alignment), 0, 6, 0, 0);
+ arrow_rawdata = gtk_expander_new
+ (_("<span size=\"small\">Raw Metadata</span>"));
+ gtk_expander_set_use_markup ((GtkExpander *) arrow_rawdata, TRUE);
+ gtk_container_add ((GtkContainer *) alignment, arrow_rawdata);
+ gtk_box_pack_start ((GtkBox *) hbox, alignment, TRUE, TRUE, 0);
+
+ scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
+ gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scrolledwindow,
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scrolledwindow,
+ GTK_SHADOW_IN);
+ gtk_container_add ((GtkContainer *) arrow_rawdata, scrolledwindow);
+
+ treeview_rawdata = gtk_tree_view_new ();
+ gtk_container_add ((GtkContainer *) scrolledwindow, treeview_rawdata);
+ gtk_tree_view_set_rules_hint ((GtkTreeView *) treeview_rawdata, TRUE);
+ gtk_tree_view_set_reorderable ((GtkTreeView *) treeview_rawdata, TRUE);
+ gtk_widget_set_size_request (treeview_rawdata, -1, 130);
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, _("Key"));
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+ gtk_tree_view_column_set_spacing (column, 4);
+ gtk_tree_view_column_set_resizable (column, FALSE);
+ gtk_tree_view_column_set_fixed_width (column, 50);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer, "text", RAWDATA_KEY,
+ NULL);
+ gtk_tree_view_append_column ((GtkTreeView *) treeview_rawdata, column);
+
+ column = gtk_tree_view_column_new ();
+ gtk_tree_view_column_set_title (column, _("Value"));
+ gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE);
+ gtk_tree_view_column_set_spacing (column, 4);
+ gtk_tree_view_column_set_resizable (column, FALSE);
+ gtk_tree_view_column_set_fixed_width (column, 50);
+
+ renderer = gtk_cell_renderer_text_new ();
+ gtk_tree_view_column_pack_start (column, renderer, FALSE);
+ gtk_tree_view_column_set_attributes (column, renderer, "text",
+ RAWDATA_VALUE, NULL);
+ gtk_tree_view_append_column ((GtkTreeView *) treeview_rawdata, column);
+
+ hbox_status_and_bbox = gtk_hbox_new (FALSE, 0);
+ gtk_box_pack_start ((GtkBox *) vbox0, hbox_status_and_bbox, FALSE, FALSE, 0);
+
+ label_mini_status = gtk_label_new ("<span size=\"small\"></span>");
+ gtk_label_set_use_markup ((GtkLabel *) label_mini_status, TRUE);
+ gtk_misc_set_alignment ((GtkMisc *) label_mini_status, 0, 0.5);
+ gtk_box_pack_start ((GtkBox *) hbox_status_and_bbox, label_mini_status,
+ TRUE, TRUE, 0);
+
+ bbox_close = gtk_hbutton_box_new ();
+ gtk_box_set_spacing ((GtkBox *) bbox_close, 6);
+ gtk_box_pack_start ((GtkBox *) hbox_status_and_bbox, bbox_close, FALSE,
+ FALSE, 0);
+ gtk_button_box_set_layout ((GtkButtonBox *) bbox_close, GTK_BUTTONBOX_END);
+
+ btn_apply = gtk_button_new_from_stock (GTK_STOCK_SAVE);
+ gtk_container_add ((GtkContainer *) bbox_close, btn_apply);
+ g_signal_connect (btn_apply, "clicked", (GCallback) infowin_update_tuple,
+ NULL);
+ gtk_widget_set_sensitive (btn_apply, FALSE);
+
+ btn_close = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
+ gtk_container_add ((GtkContainer *) bbox_close, btn_close);
+ GTK_WIDGET_SET_FLAGS (btn_close, GTK_CAN_DEFAULT);
+ g_signal_connect_swapped (btn_close, "clicked", (GCallback) gtk_widget_hide,
+ infowin);
+
+ audgui_hide_on_delete (infowin);
+ audgui_hide_on_escape (infowin);
+
+ gtk_widget_show_all (vbox0);
+}
+
+/* Converts filenames (in place) for easy reading, thus:
+ *
+ * file:///home/me/Music/My song.ogg -> Music
+ * My song.ogg
+ *
+ * file:///media/disk/My song.ogg -> /
+ * media
+ * disk
+ * My song.ogg
+ */
+static gchar * easy_read_filename (gchar * file)
+{
+ const gchar * home;
+ gint len;
+
+ if (strncmp (file, "file:///", 8))
+ return file;
+
+ home = getenv ("HOME");
+ len = (home == NULL) ? 0 : strlen (home);
+ len = (len > 0 && home[len - 1] == '/') ? len - 1 : len;
+
+ if (len > 0 && ! strncmp (file + 7, home, len) && file[len + 7] == '/')
+ {
+ string_replace_char (file + len + 8, '/', '\n');
+ return file + len + 8;
+ }
+
+ string_replace_char (file + 7, '/', '\n');
+ return file + 6;
+}
+
+static gboolean set_image_from_album_art (const gchar * filename, InputPlugin *
+ decoder)
+{
+ GdkPixbuf * pixbuf = NULL;
+ void * data;
+ gint size;
+
+ if (aud_file_read_image (filename, decoder, & data, & size))
+ {
+ pixbuf = audgui_pixbuf_from_data (data, size);
+ g_free (data);
+ }
+
+ if (pixbuf == NULL)
+ return FALSE;
+
+ audgui_pixbuf_scale_within (& pixbuf, aud_cfg->filepopup_pixelsize);
+ gtk_image_set_from_pixbuf ((GtkImage *) image_artwork, pixbuf);
+ g_object_unref (pixbuf);
+ return TRUE;
+}
+
+static void infowin_show (const gchar * filename, Tuple * tuple, InputPlugin *
+ decoder, gboolean updating_enabled)
+{
+ const gchar * string;
+ gchar * tmp;
+ GdkPixbuf * icon;
+ GtkTreeIter iter;
+ GtkListStore * store;
+ mowgli_dictionary_iteration_state_t state;
+ TupleValue * tvalue;
+ gint i;
+
+ if (infowin == NULL)
+ create_infowin ();
+ else
+ clear_infowin ();
+
+ current_file = g_strdup (filename);
+ current_decoder = decoder;
+ can_write = updating_enabled;
+
+ set_entry_str_from_field (entry_title, tuple, FIELD_TITLE, updating_enabled);
+ set_entry_str_from_field (entry_artist, tuple, FIELD_ARTIST,
+ updating_enabled);
+ set_entry_str_from_field (entry_album, tuple, FIELD_ALBUM, updating_enabled);
+ set_entry_str_from_field (entry_comment, tuple, FIELD_COMMENT,
+ updating_enabled);
+ set_entry_str_from_field (gtk_bin_get_child ((GtkBin *) entry_genre), tuple,
+ FIELD_GENRE, updating_enabled);
+
+ tmp = g_strdup (filename);
+ string_decode_percent (tmp);
+ gtk_label_set_text ((GtkLabel *) location_text, easy_read_filename (tmp));
+ g_free (tmp);
+
+ set_entry_int_from_field (entry_year, tuple, FIELD_YEAR, updating_enabled);
+ set_entry_int_from_field (entry_track, tuple, FIELD_TRACK_NUMBER,
+ updating_enabled);
+
+ infowin_label_set_text (label_format_name, tuple_get_string (tuple,
+ FIELD_CODEC, NULL));
+ infowin_label_set_text (label_quality, tuple_get_string (tuple,
+ FIELD_QUALITY, NULL));
+
+ if (tuple_get_value_type (tuple, FIELD_BITRATE, NULL) == TUPLE_INT)
+ {
+ tmp = g_strdup_printf (_("%d kb/s"), tuple_get_int (tuple,
+ FIELD_BITRATE, NULL));
+ infowin_label_set_text (label_bitrate, tmp);
+ g_free (tmp);
+ }
+ else
+ infowin_label_set_text (label_bitrate, NULL);
+
+ string = tuple_get_string (tuple, FIELD_MIMETYPE, NULL);
+ icon = mime_icon_lookup (48, string != NULL ? string : "audio/x-generic");
+
+ if (icon != NULL)
+ {
+ gtk_image_set_from_pixbuf ((GtkImage *) image_fileicon, icon);
+ g_object_unref (icon);
+ }
+
+ if (! set_image_from_album_art (filename, decoder))
+ {
+ tmp = aud_get_associated_image_file (filename);
+
+ if (tmp != NULL)
+ {
+ infowin_entry_set_image (image_artwork, tmp);
+ g_free (tmp);
+ }
+ }
+
+ store = gtk_list_store_new (RAWDATA_N_COLS, G_TYPE_STRING, G_TYPE_STRING);
+
+ for (i = 0; i < FIELD_LAST; i ++)
+ {
+ gchar * value;
+
+ if (tuple->values[i] == NULL)
+ continue;
+
+ if (tuple->values[i]->type == TUPLE_INT)
+ value = g_strdup_printf ("%d", tuple->values[i]->value.integer);
+ else if (tuple->values[i]->value.string != NULL)
+ value = g_strdup (tuple->values[i]->value.string);
+ else
+ continue;
+
+ gtk_list_store_append (store, & iter);
+ gtk_list_store_set (store, & iter, RAWDATA_KEY, tuple_fields[i].name,
+ RAWDATA_VALUE, value, -1);
+ g_free (value);
+ }
+
+ /* non-standard values are stored in a dictionary. */
+ MOWGLI_DICTIONARY_FOREACH (tvalue, & state, tuple->dict)
+ {
+ gchar * value;
+
+ if (tvalue->type == TUPLE_INT)
+ value = g_strdup_printf ("%d", tvalue->value.integer);
+ else if (tvalue->value.string != NULL)
+ value = g_strdup (tvalue->value.string);
+ else
+ continue;
+
+ gtk_list_store_append (store, & iter);
+ gtk_list_store_set (store, & iter, RAWDATA_KEY, state.cur->key,
+ RAWDATA_VALUE, value, -1);
+ g_free (value);
+ }
+
+ gtk_tree_view_set_model ((GtkTreeView *) treeview_rawdata, (GtkTreeModel *)
+ store);
+ g_object_unref (store);
+
+ gtk_window_present ((GtkWindow *) infowin);
+}
+
+void audgui_infowin_show (gint playlist, gint entry)
+{
+ const gchar * filename = aud_playlist_entry_get_filename (playlist, entry);
+ InputPlugin * decoder = aud_playlist_entry_get_decoder (playlist, entry);
+ Tuple * tuple;
+
+ g_return_if_fail (filename != NULL);
+
+ if (decoder == NULL)
+ {
+ decoder = aud_file_find_decoder (filename, FALSE);
+
+ if (decoder == NULL)
+ return;
+ }
+
+ if (aud_custom_infowin (filename, decoder))
+ return;
+
+ tuple = aud_file_read_tuple (filename, decoder);
+
+ if (tuple == NULL)
+ {
+ gchar * message = g_strdup_printf (_("No info available for %s.\n"),
+ filename);
+
+ aud_hook_call ("interface show error", message);
+ g_free (message);
+ return;
+ }
+
+ infowin_show (filename, tuple, decoder, aud_file_can_write_tuple (filename,
+ decoder));
+
+ aud_playlist_entry_set_tuple (playlist, entry, tuple);
+ /* We do not unref the tuple, as the playlist takes ownership. */
+}
+
+void audgui_infowin_show_current (void)
+{
+ gint playlist = aud_playlist_get_playing ();
+ gint position;
+
+ if (playlist == -1)
+ playlist = aud_playlist_get_active ();
+
+ position = aud_playlist_get_position (playlist);
+
+ if (position == -1)
+ return;
+
+ audgui_infowin_show (playlist, position);
+}
diff --git a/src/libaudgui/init.c b/src/libaudgui/init.c
new file mode 100644
index 0000000..ae1d1c0
--- /dev/null
+++ b/src/libaudgui/init.c
@@ -0,0 +1,29 @@
+/*
+ * libaudgui/init.c
+ * Copyright 2010 John Lindgren
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 2 or version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+#include <audacious/plugin.h>
+
+struct _AudaciousFuncTableV1 * _audvt;
+
+void audgui_init (struct _AudaciousFuncTableV1 * vtable)
+{
+ _audvt = vtable;
+}
diff --git a/src/libaudgui/init.h b/src/libaudgui/init.h
new file mode 100644
index 0000000..cbe0c79
--- /dev/null
+++ b/src/libaudgui/init.h
@@ -0,0 +1,24 @@
+/*
+ * libaudgui/init.h
+ * Copyright 2010 John Lindgren
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 2 or version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+#include <audacious/plugin.h>
+
+void audgui_init (struct _AudaciousFuncTableV1 * vtable);
diff --git a/src/libaudgui/libaudgui-gtk.h b/src/libaudgui/libaudgui-gtk.h
index ff07068..e6ac739 100644
--- a/src/libaudgui/libaudgui-gtk.h
+++ b/src/libaudgui/libaudgui-gtk.h
@@ -22,6 +22,34 @@
#ifndef LIBAUDGUI_GTK_H
#define LIBAUDGUI_GTK_H
+#include <gtk/gtk.h>
+
GtkWidget * audgui_create_effects_menu (void);
+void audgui_playlist_manager_update(void);
+void audgui_playlist_manager_ui_show(GtkWidget *mainwin);
+void audgui_playlist_manager_destroy(void);
+
+/* library-store.c */
+enum
+{
+ AUDGUI_LIBRARY_STORE_TITLE, /* G_TYPE_STRING */
+ AUDGUI_LIBRARY_STORE_FONT_WEIGHT, /* PANGO_TYPE_WEIGHT */
+ AUDGUI_LIBRARY_STORE_ENTRY_COUNT, /* G_TYPE_INT */
+ AUDGUI_LIBRARY_STORE_COLUMNS
+};
+
+GtkTreeModel * audgui_get_library_store (void);
+
+/* util.c */
+void audgui_hide_on_delete (GtkWidget * widget);
+void audgui_hide_on_escape (GtkWidget * widget);
+void audgui_destroy_on_escape (GtkWidget * widget);
+void audgui_simple_message (GtkWidget * * widget, GtkMessageType type,
+ const gchar * title, const gchar * text);
+void audgui_connect_check_box (GtkWidget * box, gboolean * setting);
+
+GdkPixbuf * audgui_pixbuf_from_data (void * data, gint size);
+void audgui_pixbuf_scale_within (GdkPixbuf * * pixbuf, gint size);
+
#endif
diff --git a/src/libaudgui/libaudgui.h b/src/libaudgui/libaudgui.h
index 924bcfd..828fafd 100644
--- a/src/libaudgui/libaudgui.h
+++ b/src/libaudgui/libaudgui.h
@@ -1,5 +1,5 @@
/* Audacious - Cross-platform multimedia player
- * Copyright (C) 2005-2009 Audacious development team.
+ * Copyright (C) 2005-2010 Audacious development team.
*
* 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
@@ -43,4 +43,16 @@ void audgui_hide_filebrowser(void);
void audgui_show_about_window(void);
void audgui_hide_about_window(void);
+/* confirm.c */
+void audgui_confirm_playlist_delete (gint playlist);
+
+/* infopopup.c */
+void audgui_infopopup_show (gint playlist, gint entry);
+void audgui_infopopup_show_current (void);
+void audgui_infopopup_hide (void);
+
+/* infowin.c */
+void audgui_infowin_show (gint playlist, gint entry);
+void audgui_infowin_show_current (void);
+
#endif /* LIBAUDGUI_H */
diff --git a/src/libaudgui/library-store.c b/src/libaudgui/library-store.c
new file mode 100644
index 0000000..b2054bf
--- /dev/null
+++ b/src/libaudgui/library-store.c
@@ -0,0 +1,366 @@
+/*
+ * libaudgui/library-store.c
+ * Copyright 2010 John Lindgren
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 2 or version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+#include <audacious/plugin.h>
+
+#include "libaudgui-gtk.h"
+
+typedef GObjectClass LibraryStoreClass;
+
+typedef struct
+{
+ GObject parent;
+ gint rows, active;
+}
+LibraryStore;
+
+static void library_store_init (LibraryStore * store)
+{
+ store->rows = aud_playlist_count ();
+ store->active = aud_playlist_get_active ();
+}
+
+static GtkTreeModelFlags library_store_get_flags (GtkTreeModel * model)
+{
+ return GTK_TREE_MODEL_LIST_ONLY;
+}
+
+static gint library_store_get_n_columns (GtkTreeModel * model)
+{
+ return AUDGUI_LIBRARY_STORE_COLUMNS;
+}
+
+static GType library_store_get_column_type (GtkTreeModel * model, gint column)
+{
+ switch (column)
+ {
+ case AUDGUI_LIBRARY_STORE_TITLE:
+ return G_TYPE_STRING;
+ case AUDGUI_LIBRARY_STORE_FONT_WEIGHT:
+ return PANGO_TYPE_WEIGHT;
+ case AUDGUI_LIBRARY_STORE_ENTRY_COUNT:
+ return G_TYPE_INT;
+ default:
+ return G_TYPE_INVALID;
+ }
+}
+
+static gboolean library_store_get_iter (GtkTreeModel * model, GtkTreeIter *
+ iter, GtkTreePath * path)
+{
+ LibraryStore * store = (LibraryStore *) model;
+ gint playlist = gtk_tree_path_get_indices (path)[0];
+
+ if (playlist < 0 || playlist >= store->rows)
+ return FALSE;
+
+ iter->user_data = GINT_TO_POINTER (playlist);
+ return TRUE;
+}
+
+static GtkTreePath * library_store_get_path (GtkTreeModel * model, GtkTreeIter *
+ iter)
+{
+ return gtk_tree_path_new_from_indices (GPOINTER_TO_INT (iter->user_data), -1);
+}
+
+static void library_store_get_value (GtkTreeModel * model, GtkTreeIter * iter,
+ gint column, GValue * value)
+{
+ LibraryStore * store = (LibraryStore *) model;
+ gint playlist = GPOINTER_TO_INT (iter->user_data);
+
+ switch (column)
+ {
+ case AUDGUI_LIBRARY_STORE_TITLE:
+ g_value_init (value, G_TYPE_STRING);
+ g_value_set_string (value, aud_playlist_get_title (playlist));
+ break;
+ case AUDGUI_LIBRARY_STORE_FONT_WEIGHT:
+ g_value_init (value, PANGO_TYPE_WEIGHT);
+ g_value_set_enum (value, (playlist == store->active) ? PANGO_WEIGHT_BOLD
+ : PANGO_WEIGHT_NORMAL);
+ break;
+ case AUDGUI_LIBRARY_STORE_ENTRY_COUNT:
+ g_value_init (value, G_TYPE_INT);
+ g_value_set_int (value, aud_playlist_entry_count (playlist));
+ break;
+ }
+}
+
+static gboolean library_store_iter_next (GtkTreeModel * model, GtkTreeIter *
+ iter)
+{
+ if (GPOINTER_TO_INT (iter->user_data) + 1 < aud_playlist_count ())
+ {
+ iter->user_data = GINT_TO_POINTER (GPOINTER_TO_INT (iter->user_data) + 1);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean library_store_iter_children (GtkTreeModel * model, GtkTreeIter *
+ iter, GtkTreeIter * parent)
+{
+ if (parent == NULL) /* top level */
+ {
+ /* there is always at least one playlist */
+ iter->user_data = GINT_TO_POINTER (0);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean library_store_iter_has_child (GtkTreeModel * model,
+ GtkTreeIter * iter)
+{
+ return FALSE;
+}
+
+static gint library_store_iter_n_children (GtkTreeModel * model, GtkTreeIter *
+ iter)
+{
+ LibraryStore * store = (LibraryStore *) model;
+
+ if (iter == NULL) /* top level */
+ return store->rows;
+
+ return 0;
+}
+
+static gboolean library_store_iter_nth_child (GtkTreeModel * model,
+ GtkTreeIter * iter, GtkTreeIter * parent, gint n)
+{
+ LibraryStore * store = (LibraryStore *) model;
+
+ if (parent != NULL) /* not top level */
+ return FALSE;
+
+ if (n < 0 || n >= store->rows)
+ return FALSE;
+
+ iter->user_data = GINT_TO_POINTER (n);
+ return TRUE;
+}
+
+static gboolean library_store_iter_parent (GtkTreeModel * model, GtkTreeIter *
+ iter, GtkTreeIter * child)
+{
+ return FALSE;
+}
+
+static void interface_init (GtkTreeModelIface * interface)
+{
+ interface->get_flags = library_store_get_flags;
+ interface->get_n_columns = library_store_get_n_columns;
+ interface->get_column_type = library_store_get_column_type;
+ interface->get_iter = library_store_get_iter;
+ interface->get_path = library_store_get_path;
+ interface->get_value = library_store_get_value;
+ interface->iter_next = library_store_iter_next;
+ interface->iter_children = library_store_iter_children;
+ interface->iter_has_child = library_store_iter_has_child;
+ interface->iter_n_children = library_store_iter_n_children;
+ interface->iter_nth_child = library_store_iter_nth_child;
+ interface->iter_parent = library_store_iter_parent;
+}
+
+static const GInterfaceInfo interface_info =
+{
+ .interface_init = (GInterfaceInitFunc) interface_init,
+ .interface_finalize = NULL,
+ .interface_data = NULL,
+};
+
+static gboolean library_store_drag_data_get (GtkTreeDragSource * source,
+ GtkTreePath * path, GtkSelectionData * data)
+{
+ return gtk_tree_set_row_drag_data (data, (GtkTreeModel *) source, path);
+}
+
+static gboolean library_store_drag_data_delete (GtkTreeDragSource * source,
+ GtkTreePath * path)
+{
+ return TRUE;
+}
+
+static void source_init (GtkTreeDragSourceIface * interface)
+{
+ interface->drag_data_get = library_store_drag_data_get;
+ interface->drag_data_delete = library_store_drag_data_delete;
+}
+
+static const GInterfaceInfo source_info =
+{
+ .interface_init = (GInterfaceInitFunc) source_init,
+ .interface_finalize = NULL,
+ .interface_data = NULL,
+};
+
+static gboolean library_store_drag_data_received (GtkTreeDragDest * dest,
+ GtkTreePath * dest_path, GtkSelectionData * data)
+{
+ LibraryStore * store = (LibraryStore *) dest;
+ GtkTreeModel * model;
+ GtkTreePath * source_path, * top;
+ gint from, to, count;
+ gint order[store->rows];
+
+ if (! gtk_tree_get_row_drag_data (data, & model, & source_path))
+ return FALSE;
+
+ from = gtk_tree_path_get_indices (source_path)[0];
+ to = gtk_tree_path_get_indices (dest_path)[0];
+
+ /* GTK gives us the number of the row before which we are to put the row.
+ * We want the number of the row where the row will end up. */
+ if (to > from)
+ to --;
+
+ if (from < 0 || from >= store->rows || to < 0 || to >= store->rows)
+ return FALSE;
+
+ aud_playlist_reorder (from, to, 1);
+
+ for (count = 0; count < from; count ++)
+ order[count] = count;
+
+ if (from < to)
+ {
+ for (count = from; count < to; count ++)
+ order[count] = count + 1;
+ }
+ else
+ {
+ for (count = to; count < from; count ++)
+ order[count + 1] = count;
+ }
+
+ order[to] = from;
+
+ top = gtk_tree_path_new ();
+ gtk_tree_model_rows_reordered (model, top, NULL, order);
+ gtk_tree_path_free (top);
+
+ return TRUE;
+}
+
+gboolean library_store_row_drop_possible (GtkTreeDragDest * dest,
+ GtkTreePath * path, GtkSelectionData * selection_data)
+{
+ LibraryStore * store = (LibraryStore *) dest;
+ gint before = gtk_tree_path_get_indices (path)[0];
+
+ return (before >= 0 && before <= store->rows);
+}
+
+static void dest_init (GtkTreeDragDestIface * interface)
+{
+ interface->drag_data_received = library_store_drag_data_received;
+ interface->row_drop_possible = library_store_row_drop_possible;
+}
+
+static const GInterfaceInfo dest_info =
+{
+ .interface_init = (GInterfaceInitFunc) dest_init,
+ .interface_finalize = NULL,
+ .interface_data = NULL,
+};
+
+static GType library_store_get_type (void)
+{
+ static GType type = 0;
+
+ if (! type)
+ {
+ type = g_type_register_static_simple (G_TYPE_OBJECT, "LibraryStore",
+ sizeof (LibraryStoreClass), NULL, sizeof (LibraryStore),
+ (GInstanceInitFunc) library_store_init, 0);
+ g_type_add_interface_static (type, GTK_TYPE_TREE_MODEL, & interface_info);
+ g_type_add_interface_static (type, GTK_TYPE_TREE_DRAG_SOURCE,
+ & source_info);
+ g_type_add_interface_static (type, GTK_TYPE_TREE_DRAG_DEST, & dest_info);
+ }
+
+ return type;
+}
+
+static void library_store_update (GtkTreeModel * model)
+{
+ LibraryStore * store = (LibraryStore *) model;
+ gint old_rows = store->rows;
+ GtkTreePath * path;
+ GtkTreeIter iter;
+ gint row;
+
+ store->rows = aud_playlist_count ();
+ store->active = aud_playlist_get_active ();
+
+ if (store->rows < old_rows)
+ {
+ path = gtk_tree_path_new_from_indices (store->rows, -1);
+
+ for (row = store->rows; row < old_rows; row ++)
+ gtk_tree_model_row_deleted (model, path);
+
+ gtk_tree_path_free (path);
+ old_rows = store->rows;
+ }
+
+ path = gtk_tree_path_new_first ();
+
+ for (row = 0; row < old_rows; row ++)
+ {
+ iter.user_data = GINT_TO_POINTER (row);
+ gtk_tree_model_row_changed (model, path, & iter);
+ gtk_tree_path_next (path);
+ }
+
+ for (; row < store->rows; row ++)
+ {
+ iter.user_data = GINT_TO_POINTER (row);
+ gtk_tree_model_row_inserted (model, path, & iter);
+ gtk_tree_path_next (path);
+ }
+
+ gtk_tree_path_free (path);
+}
+
+static void update_cb (void * data, void * user_data)
+{
+ if (GPOINTER_TO_INT (data) >= PLAYLIST_UPDATE_STRUCTURE)
+ library_store_update ((GtkTreeModel *) user_data);
+}
+
+GtkTreeModel * audgui_get_library_store (void)
+{
+ static GtkTreeModel * store = NULL;
+
+ if (store == NULL)
+ {
+ store = (GtkTreeModel *) g_object_new (library_store_get_type (), NULL);
+ aud_hook_associate ("playlist update", update_cb, store);
+ }
+
+ return store;
+}
diff --git a/src/libaudgui/ui_jumptotrack.c b/src/libaudgui/ui_jumptotrack.c
index def34a8..02afe99 100644
--- a/src/libaudgui/ui_jumptotrack.c
+++ b/src/libaudgui/ui_jumptotrack.c
@@ -329,6 +329,12 @@ static void watchdog (void * hook_data, void * user_data)
NULL)
return;
+ if (cache != NULL)
+ {
+ ui_jump_to_track_cache_free (cache);
+ cache = NULL;
+ }
+
tree = g_object_get_data (storage, "treeview");
/* If it's only a metadata update, save and restore the cursor position. */
diff --git a/src/libaudgui/ui_playlist_manager.c b/src/libaudgui/ui_playlist_manager.c
new file mode 100644
index 0000000..2c24374
--- /dev/null
+++ b/src/libaudgui/ui_playlist_manager.c
@@ -0,0 +1,263 @@
+/* Audacious - Cross-platform multimedia player
+ * Copyright (C) 2005-2010 Audacious development team.
+ *
+ * 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; under version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses>.
+ *
+ * The Audacious team does not consider modular code linking to
+ * Audacious or using our public API to be a derived work.
+ */
+
+#include <audacious/i18n.h>
+#include <audacious/plugin.h>
+
+#include "libaudgui.h"
+#include "libaudgui-gtk.h"
+
+static gint iter_to_row (GtkTreeModel * model, GtkTreeIter * iter)
+{
+ GtkTreePath * path = gtk_tree_model_get_path (model, iter);
+ gint row = gtk_tree_path_get_indices (path)[0];
+
+ gtk_tree_path_free (path);
+ return row;
+}
+
+static gint get_selected_row (GtkWidget * list)
+{
+ GtkTreeSelection * selection = gtk_tree_view_get_selection ((GtkTreeView *)
+ list);
+ GtkTreeModel * model;
+ GtkTreeIter iter;
+
+ if (! gtk_tree_selection_get_selected (selection, & model, & iter))
+ return -1;
+
+ return iter_to_row (model, & iter);
+}
+
+static void set_selected_row (GtkWidget * list, gint row)
+{
+ GtkTreeSelection * selection = gtk_tree_view_get_selection ((GtkTreeView *)
+ list);
+ GtkTreePath * path = gtk_tree_path_new_from_indices (row, -1);
+
+ gtk_tree_selection_select_path (selection, path);
+ gtk_tree_path_free (path);
+}
+
+static void save_position (GtkWidget * window)
+{
+ gtk_window_get_position ((GtkWindow *) window,
+ & aud_cfg->playlist_manager_x, & aud_cfg->playlist_manager_y);
+ gtk_window_get_size ((GtkWindow *) window,
+ & aud_cfg->playlist_manager_width, & aud_cfg->playlist_manager_height);
+}
+
+static gboolean hide_cb (GtkWidget * window)
+{
+ save_position (window);
+ gtk_widget_hide (window);
+ return TRUE;
+}
+
+static void activate_cb (GtkTreeView * list, GtkTreePath * path,
+ GtkTreeViewColumn * column, GtkWidget * window)
+{
+ aud_playlist_set_active (gtk_tree_path_get_indices (path)[0]);
+
+ if (aud_cfg->playlist_manager_close_on_activate)
+ hide_cb (window);
+}
+
+static void new_cb (GtkButton * button, void * unused)
+{
+ aud_playlist_insert (-1);
+}
+
+static void delete_cb (GtkButton * button, GtkWidget * list)
+{
+ gint playlist = get_selected_row (list);
+
+ if (playlist != -1)
+ audgui_confirm_playlist_delete (playlist);
+}
+
+static void rename_cb (GtkButton * button, GtkWidget * lv)
+{
+ GtkTreeSelection *listsel = gtk_tree_view_get_selection( GTK_TREE_VIEW(lv) );
+ GtkTreeModel *store;
+ GtkTreeIter iter;
+
+ if ( gtk_tree_selection_get_selected( listsel , &store , &iter ) == TRUE )
+ {
+ GtkTreePath *path = gtk_tree_model_get_path( GTK_TREE_MODEL(store) , &iter );
+ GtkCellRenderer *rndrname = g_object_get_data( G_OBJECT(lv) , "rn" );
+ /* set the name renderer to editable and start editing */
+ g_object_set( G_OBJECT(rndrname) , "editable" , TRUE , NULL );
+ gtk_tree_view_set_cursor_on_cell ((GtkTreeView *) lv, path,
+ gtk_tree_view_get_column ((GtkTreeView *) lv,
+ AUDGUI_LIBRARY_STORE_TITLE), rndrname, TRUE);
+ gtk_tree_path_free( path );
+ }
+}
+
+static void
+playlist_manager_cb_lv_name_edited ( GtkCellRendererText *cell , gchar *path_string ,
+ gchar *new_text , gpointer listview )
+{
+ /* this is currently used to change playlist names */
+ GtkTreeModel *store = gtk_tree_view_get_model( GTK_TREE_VIEW(listview) );
+ GtkTreeIter iter;
+
+ if ( gtk_tree_model_get_iter_from_string( store , &iter , path_string ) == TRUE )
+ aud_playlist_set_title (iter_to_row (store, & iter), new_text);
+
+ /* set the renderer uneditable again */
+ g_object_set( G_OBJECT(cell) , "editable" , FALSE , NULL );
+}
+
+static void save_config_cb (void * hook_data, void * user_data)
+{
+#if GTK_CHECK_VERSION (2, 18, 0)
+ if (gtk_widget_get_visible ((GtkWidget *) user_data))
+#else
+ if (GTK_WIDGET_VISIBLE ((GtkWidget *) user_data))
+#endif
+ save_position ((GtkWidget *) user_data);
+}
+
+static GtkWidget * playman_win = NULL;
+
+void
+audgui_playlist_manager_ui_show (GtkWidget *mainwin)
+{
+ GtkWidget *playman_vbox;
+ GtkWidget * playman_pl_lv, * playman_pl_lv_sw;
+ GtkCellRenderer *playman_pl_lv_textrndr_name, *playman_pl_lv_textrndr_entriesnum;
+ GtkTreeViewColumn *playman_pl_lv_col_name, *playman_pl_lv_col_entriesnum;
+ GtkWidget *playman_bbar_hbbox;
+ GtkWidget * rename_button, * new_button, * delete_button;
+ GtkWidget * hbox, * button;
+ GdkGeometry playman_win_hints;
+
+ if ( playman_win != NULL )
+ {
+ gtk_window_present( GTK_WINDOW(playman_win) );
+ return;
+ }
+
+ playman_win = gtk_window_new( GTK_WINDOW_TOPLEVEL );
+ gtk_window_set_type_hint( GTK_WINDOW(playman_win), GDK_WINDOW_TYPE_HINT_DIALOG );
+ gtk_window_set_transient_for( GTK_WINDOW(playman_win) , GTK_WINDOW(mainwin) );
+ gtk_window_set_title( GTK_WINDOW(playman_win), _("Playlist Manager") );
+ gtk_container_set_border_width ((GtkContainer *) playman_win, 6);
+ playman_win_hints.min_width = 400;
+ playman_win_hints.min_height = 250;
+ gtk_window_set_geometry_hints( GTK_WINDOW(playman_win) , GTK_WIDGET(playman_win) ,
+ &playman_win_hints , GDK_HINT_MIN_SIZE );
+
+ if (aud_cfg->playlist_manager_width)
+ {
+ gtk_window_move ((GtkWindow *) playman_win, aud_cfg->playlist_manager_x,
+ aud_cfg->playlist_manager_y);
+ gtk_window_set_default_size ((GtkWindow *) playman_win,
+ aud_cfg->playlist_manager_width, aud_cfg->playlist_manager_height);
+ }
+
+ g_signal_connect ((GObject *) playman_win, "delete-event", (GCallback)
+ hide_cb, NULL);
+
+ playman_vbox = gtk_vbox_new (FALSE, 6);
+ gtk_container_add( GTK_CONTAINER(playman_win) , playman_vbox );
+
+ playman_pl_lv = gtk_tree_view_new_with_model (audgui_get_library_store ());
+ gtk_tree_view_set_reorderable ((GtkTreeView *) playman_pl_lv, TRUE);
+
+ playman_pl_lv_textrndr_entriesnum = gtk_cell_renderer_text_new(); /* uneditable */
+ playman_pl_lv_textrndr_name = gtk_cell_renderer_text_new(); /* can become editable */
+ g_object_set( G_OBJECT(playman_pl_lv_textrndr_entriesnum) , "weight-set" , TRUE , NULL );
+ g_object_set( G_OBJECT(playman_pl_lv_textrndr_name) , "weight-set" , TRUE , NULL );
+ g_signal_connect( G_OBJECT(playman_pl_lv_textrndr_name) , "edited" ,
+ G_CALLBACK(playlist_manager_cb_lv_name_edited) , playman_pl_lv );
+ g_object_set_data( G_OBJECT(playman_pl_lv) , "rn" , playman_pl_lv_textrndr_name );
+
+ playman_pl_lv_col_name = gtk_tree_view_column_new_with_attributes
+ (_("Playlist"), playman_pl_lv_textrndr_name, "text",
+ AUDGUI_LIBRARY_STORE_TITLE, "weight", AUDGUI_LIBRARY_STORE_FONT_WEIGHT,
+ NULL);
+ gtk_tree_view_column_set_expand( GTK_TREE_VIEW_COLUMN(playman_pl_lv_col_name) , TRUE );
+ gtk_tree_view_append_column( GTK_TREE_VIEW(playman_pl_lv), playman_pl_lv_col_name );
+
+ playman_pl_lv_col_entriesnum = gtk_tree_view_column_new_with_attributes
+ (_("Entries"), playman_pl_lv_textrndr_entriesnum, "text",
+ AUDGUI_LIBRARY_STORE_ENTRY_COUNT, "weight",
+ AUDGUI_LIBRARY_STORE_FONT_WEIGHT, NULL);
+ gtk_tree_view_column_set_expand( GTK_TREE_VIEW_COLUMN(playman_pl_lv_col_entriesnum) , FALSE );
+ gtk_tree_view_append_column( GTK_TREE_VIEW(playman_pl_lv), playman_pl_lv_col_entriesnum );
+
+ playman_pl_lv_sw = gtk_scrolled_window_new( NULL , NULL );
+ gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) playman_pl_lv_sw,
+ GTK_SHADOW_IN);
+ gtk_scrolled_window_set_policy ((GtkScrolledWindow *) playman_pl_lv_sw,
+ GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+ gtk_container_add( GTK_CONTAINER(playman_pl_lv_sw) , playman_pl_lv );
+ gtk_box_pack_start ((GtkBox *) playman_vbox, playman_pl_lv_sw, TRUE, TRUE, 0);
+
+ /* button bar */
+ playman_bbar_hbbox = gtk_hbutton_box_new();
+ gtk_button_box_set_layout( GTK_BUTTON_BOX(playman_bbar_hbbox) , GTK_BUTTONBOX_END );
+ gtk_box_set_spacing ((GtkBox *) playman_bbar_hbbox, 6);
+
+ rename_button = gtk_button_new_with_mnemonic (_("_Rename"));
+ gtk_button_set_image ((GtkButton *) rename_button, gtk_image_new_from_stock
+ (GTK_STOCK_EDIT, GTK_ICON_SIZE_BUTTON));
+ new_button = gtk_button_new_from_stock (GTK_STOCK_NEW);
+ delete_button = gtk_button_new_from_stock (GTK_STOCK_DELETE);
+
+ gtk_container_add ((GtkContainer *) playman_bbar_hbbox, rename_button);
+ gtk_button_box_set_child_secondary ((GtkButtonBox *) playman_bbar_hbbox,
+ rename_button, TRUE);
+ gtk_container_add ((GtkContainer *) playman_bbar_hbbox, new_button);
+ gtk_container_add ((GtkContainer *) playman_bbar_hbbox, delete_button);
+
+ gtk_box_pack_start( GTK_BOX(playman_vbox) , playman_bbar_hbbox , FALSE , FALSE , 0 );
+
+ g_signal_connect ((GObject *) playman_pl_lv, "row-activated", (GCallback)
+ activate_cb, playman_win);
+ g_signal_connect ((GObject *) rename_button, "clicked", (GCallback)
+ rename_cb, playman_pl_lv);
+ g_signal_connect ((GObject *) new_button, "clicked", (GCallback) new_cb,
+ playman_pl_lv);
+ g_signal_connect ((GObject *) delete_button, "clicked", (GCallback)
+ delete_cb, playman_pl_lv);
+
+ set_selected_row (playman_pl_lv, aud_playlist_get_active ());
+
+ hbox = gtk_hbox_new (FALSE, 6);
+ gtk_box_pack_start ((GtkBox *) playman_vbox, hbox, FALSE, FALSE, 0);
+ button = gtk_check_button_new_with_mnemonic
+ (_("_Close dialog on activating playlist"));
+ gtk_box_pack_start ((GtkBox *) hbox, button, FALSE, FALSE, 0);
+ audgui_connect_check_box (button,
+ & aud_cfg->playlist_manager_close_on_activate);
+
+ gtk_widget_show_all( playman_win );
+
+ aud_hook_associate ("config save", save_config_cb, playman_win);
+}
+
+void audgui_playlist_manager_destroy(void)
+{
+ if (playman_win)
+ hide_cb (playman_win);
+}
diff --git a/src/libaudgui/util.c b/src/libaudgui/util.c
new file mode 100644
index 0000000..f2aadbf
--- /dev/null
+++ b/src/libaudgui/util.c
@@ -0,0 +1,127 @@
+/*
+ * libaudgui/util.c
+ * Copyright 2010 John Lindgren
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 2 or version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+#include <gdk/gdkkeysyms.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gtk/gtk.h>
+
+#include "libaudgui.h"
+#include "libaudgui-gtk.h"
+
+void audgui_hide_on_delete (GtkWidget * widget)
+{
+ g_signal_connect (widget, "delete-event", (GCallback)
+ gtk_widget_hide_on_delete, NULL);
+}
+
+static gboolean escape_cb (GtkWidget * widget, GdkEventKey * event, void
+ (* action) (GtkWidget * widget))
+{
+ if (event->keyval == GDK_Escape)
+ {
+ action (widget);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void audgui_hide_on_escape (GtkWidget * widget)
+{
+ g_signal_connect (widget, "key-press-event", (GCallback) escape_cb,
+ gtk_widget_hide);
+}
+
+void audgui_destroy_on_escape (GtkWidget * widget)
+{
+ g_signal_connect (widget, "key-press-event", (GCallback) escape_cb,
+ gtk_widget_destroy);
+}
+
+static void toggle_cb (GtkToggleButton * toggle, gboolean * setting)
+{
+ * setting = gtk_toggle_button_get_active (toggle);
+}
+
+void audgui_connect_check_box (GtkWidget * box, gboolean * setting)
+{
+ gtk_toggle_button_set_active ((GtkToggleButton *) box, * setting);
+ g_signal_connect ((GObject *) box, "toggled", (GCallback) toggle_cb, setting);
+}
+
+void audgui_simple_message (GtkWidget * * widget, GtkMessageType type,
+ const gchar * title, const gchar * text)
+{
+ if (* widget == NULL)
+ {
+ * widget = gtk_message_dialog_new (NULL, 0, type, GTK_BUTTONS_OK, "%s",
+ text);
+ gtk_window_set_title ((GtkWindow *) * widget, title);
+
+ g_signal_connect (* widget, "response", (GCallback) gtk_widget_destroy,
+ NULL);
+ audgui_destroy_on_escape (* widget);
+ g_signal_connect (* widget, "destroy", (GCallback) gtk_widget_destroyed,
+ widget);
+ }
+
+ gtk_window_present ((GtkWindow *) * widget);
+}
+
+GdkPixbuf * audgui_pixbuf_from_data (void * data, gint size)
+{
+ GdkPixbuf * pixbuf = NULL;
+ GdkPixbufLoader * loader = gdk_pixbuf_loader_new ();
+
+ if (gdk_pixbuf_loader_write (loader, data, size, NULL))
+ pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
+
+ gdk_pixbuf_loader_close (loader, NULL);
+ return pixbuf;
+}
+
+void audgui_pixbuf_scale_within (GdkPixbuf * * pixbuf, gint size)
+{
+ gint width = gdk_pixbuf_get_width (* pixbuf);
+ gint height = gdk_pixbuf_get_height (* pixbuf);
+ GdkPixbuf * pixbuf2;
+
+ if (width > height)
+ {
+ height = size * height / width;
+ width = size;
+ }
+ else
+ {
+ width = size * width / height;
+ height = size;
+ }
+
+ if (width < 1)
+ width = 1;
+ if (height < 1)
+ height = 1;
+
+ pixbuf2 = gdk_pixbuf_scale_simple (* pixbuf, width, height,
+ GDK_INTERP_BILINEAR);
+ g_object_unref (* pixbuf);
+ * pixbuf = pixbuf2;
+}
diff --git a/src/libaudtag/Makefile b/src/libaudtag/Makefile
index 914fa8c..127c8c7 100644
--- a/src/libaudtag/Makefile
+++ b/src/libaudtag/Makefile
@@ -5,16 +5,14 @@ LIB_MINOR = 0
SRCS = audtag.c \
util.c \
tag_module.c \
- wma/guid.c \
- wma/wma.c \
- id3/id3.c \
- ape/ape.c \
- aac/aac.c
-INCLUDES = audtag.h util.h
+ id3/id3v1.c \
+ id3/id3v24.c \
+ ape/ape.c
+
+INCLUDES = audtag.h
include ../../buildsys.mk
include ../../extra.mk
-includesubdir = libaudtag
CPPFLAGS += ${LIB_CPPFLAGS} ${GLIB_CFLAGS} ${MOWGLI_CFLAGS} -D_AUDACIOUS_CORE -I.. -I../..
CFLAGS += ${LIB_CFLAGS}
diff --git a/src/libaudtag/aac/aac.c b/src/libaudtag/aac/aac.c
index 0b04a9e..87f63f9 100644
--- a/src/libaudtag/aac/aac.c
+++ b/src/libaudtag/aac/aac.c
@@ -1,3 +1,22 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
#include <glib/gstdio.h>
#include <libaudcore/tuple.h>
@@ -6,60 +25,66 @@
#include "aac.h"
#include "../util.h"
-static const char* ID3v1GenreList[] = {
- "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
- "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies",
- "Other", "Pop", "R&B", "Rap", "Reggae", "Rock",
- "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
- "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk",
- "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House",
- "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass",
- "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock",
- "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk",
- "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta",
- "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
- "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
- "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
- "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing",
- "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde",
- "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band",
- "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson",
- "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
- "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
- "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet",
- "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall",
- "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror",
- "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat",
- "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover", "Contemporary C",
- "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop",
- "SynthPop",
+static const char *ID3v1GenreList[] = {
+ "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk",
+ "Grunge", "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies",
+ "Other", "Pop", "R&B", "Rap", "Reggae", "Rock",
+ "Techno", "Industrial", "Alternative", "Ska", "Death Metal", "Pranks",
+ "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop", "Vocal", "Jazz+Funk",
+ "Fusion", "Trance", "Classical", "Instrumental", "Acid", "House",
+ "Game", "Sound Clip", "Gospel", "Noise", "AlternRock", "Bass",
+ "Soul", "Punk", "Space", "Meditative", "Instrumental Pop", "Instrumental Rock",
+ "Ethnic", "Gothic", "Darkwave", "Techno-Industrial", "Electronic", "Pop-Folk",
+ "Eurodance", "Dream", "Southern Rock", "Comedy", "Cult", "Gangsta",
+ "Top 40", "Christian Rap", "Pop/Funk", "Jungle", "Native American", "Cabaret",
+ "New Wave", "Psychadelic", "Rave", "Showtunes", "Trailer", "Lo-Fi",
+ "Tribal", "Acid Punk", "Acid Jazz", "Polka", "Retro", "Musical",
+ "Rock & Roll", "Hard Rock", "Folk", "Folk/Rock", "National Folk", "Swing",
+ "Fast-Fusion", "Bebob", "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde",
+ "Gothic Rock", "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock", "Big Band",
+ "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech", "Chanson",
+ "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass", "Primus",
+ "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
+ "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet",
+ "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall",
+ "Goa", "Drum & Bass", "Club House", "Hardcore", "Terror",
+ "Indie", "BritPop", "NegerPunk", "Polsk Punk", "Beat",
+ "Christian Gangsta", "Heavy Metal", "Black Metal", "Crossover", "Contemporary C",
+ "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop",
+ "SynthPop",
};
-gchar* atom_types[] = {"\251alb", "\251nam", "cprt", "\251art", "\251ART", "trkn", "\251day", "gnre", "desc"};
+gchar *atom_types[] = { "\251alb", "\251nam", "cprt", "\251art", "\251ART", "trkn", "\251day", "gnre", "desc" };
-tag_module_t aac = {aac_can_handle_file, aac_populate_tuple_from_file, aac_write_tuple_to_file};
+Atom *readAtom(VFSFile * fd)
+{
+ guint32 size = read_BEuint32(fd);
+ if (size > vfs_fsize(fd))
+ return NULL;
-Atom *readAtom(VFSFile *fd) {
Atom *atom = g_new0(Atom, 1);
- atom->size = read_BEuint32(fd);
+ atom->size = size;
atom->name = read_char_data(fd, 4);
atom->body = read_char_data(fd, atom->size - 8);
atom->type = 0;
return atom;
}
-void writeAtom(VFSFile *fd, Atom *atom) {
+void writeAtom(VFSFile * fd, Atom * atom)
+{
write_BEuint32(fd, atom->size);
vfs_fwrite(atom->name, 4, 1, fd);
vfs_fwrite(atom->body, atom->size - 8, 1, fd);
}
-void printAtom(Atom *atom) {
+void printAtom(Atom * atom)
+{
AUDDBG("size = %x\n", atom->size);
AUDDBG("name = %s\n", atom->name);
}
-StrDataAtom *readStrDataAtom(VFSFile *fd) {
+StrDataAtom *readStrDataAtom(VFSFile * fd)
+{
StrDataAtom *atom = g_new0(StrDataAtom, 1);
atom->atomsize = read_BEuint32(fd);
atom->name = read_char_data(fd, 4);
@@ -72,7 +97,8 @@ StrDataAtom *readStrDataAtom(VFSFile *fd) {
return atom;
}
-void writeStrDataAtom(VFSFile *fd, StrDataAtom *atom) {
+void writeStrDataAtom(VFSFile * fd, StrDataAtom * atom)
+{
write_BEuint32(fd, atom->atomsize);
vfs_fwrite(atom->name, 4, 1, fd);
write_BEuint32(fd, atom->datasize);
@@ -82,7 +108,8 @@ void writeStrDataAtom(VFSFile *fd, StrDataAtom *atom) {
vfs_fwrite(atom->data, atom->datasize - 16, 1, fd);
}
-Atom *findAtom(VFSFile *fd, gchar* name) {
+Atom *findAtom(VFSFile * fd, gchar * name)
+{
Atom *atom = readAtom(fd);
while (strcmp(atom->name, name) && !vfs_feof(fd))
{
@@ -98,7 +125,8 @@ Atom *findAtom(VFSFile *fd, gchar* name) {
return atom;
}
-Atom *getilstAtom(VFSFile *fd) {
+Atom *getilstAtom(VFSFile * fd)
+{
Atom *moov = findAtom(fd, MOOV);
// search atom childs
@@ -112,8 +140,7 @@ Atom *getilstAtom(VFSFile *fd) {
vfs_fseek(fd, -(meta->size - 11), SEEK_CUR);
Atom *ilst = findAtom(fd, ILST);
- int zz = vfs_ftell(fd);
- AUDDBG("zzz = %d\n", zz);
+ AUDDBG("zzz = %d\n", vfs_ftell(fd));
ilstFileOffset = vfs_ftell(fd) - ilst->size;
vfs_fseek(fd, -(ilst->size - 7), SEEK_CUR);
@@ -121,7 +148,8 @@ Atom *getilstAtom(VFSFile *fd) {
}
-int getAtomID(gchar* name) {
+int getAtomID(gchar * name)
+{
g_return_val_if_fail(name != NULL, -1);
int i = 0;
for (i = 0; i < MP4_ITEMS_NO; i++)
@@ -132,7 +160,8 @@ int getAtomID(gchar* name) {
return -1;
}
-StrDataAtom *makeAtomWithData(const gchar* data, StrDataAtom *atom, int field) {
+StrDataAtom *makeAtomWithData(const gchar * data, StrDataAtom * atom, int field)
+{
guint32 charsize = strlen(data);
atom->atomsize = charsize + 24;
atom->name = atom_types[field];
@@ -140,13 +169,14 @@ StrDataAtom *makeAtomWithData(const gchar* data, StrDataAtom *atom, int field) {
atom->dataname = "data";
atom->vflag = 0x0;
atom->nullData = 0x0;
- atom->data = (gchar*) data;
+ atom->data = (gchar *) data;
atom->type = 1;
return atom;
}
-void writeAtomListToFile(VFSFile* from, VFSFile *to, int offset, mowgli_list_t *list) {
+void writeAtomListToFile(VFSFile * from, VFSFile * to, int offset, mowgli_list_t * list)
+{
//read free atom if we have any :D
guint32 oset = ilstFileOffset + ilstAtom->size;
vfs_fseek(from, oset, SEEK_SET);
@@ -174,13 +204,15 @@ void writeAtomListToFile(VFSFile* from, VFSFile *to, int offset, mowgli_list_t *
mowgli_node_t *n, *tn;
- MOWGLI_LIST_FOREACH_SAFE(n, tn, list->head) {
- if (((Atom*) (n->data))->type == 0)
+ MOWGLI_LIST_FOREACH_SAFE(n, tn, list->head)
+ {
+ if (((Atom *) (n->data))->type == 0)
{
- writeAtom(to, (Atom*) (n->data));
- } else
+ writeAtom(to, (Atom *) (n->data));
+ }
+ else
{
- writeStrDataAtom(to, (StrDataAtom*) (n->data));
+ writeStrDataAtom(to, (StrDataAtom *) (n->data));
}
}
@@ -188,8 +220,9 @@ void writeAtomListToFile(VFSFile* from, VFSFile *to, int offset, mowgli_list_t *
if (atoms_before_free->count != 0)
{
- MOWGLI_LIST_FOREACH_SAFE(n, tn, list->head) {
- writeAtom(to, (Atom*) (n->data));
+ MOWGLI_LIST_FOREACH_SAFE(n, tn, list->head)
+ {
+ writeAtom(to, (Atom *) (n->data));
}
}
if (atom != NULL)
@@ -199,14 +232,18 @@ void writeAtomListToFile(VFSFile* from, VFSFile *to, int offset, mowgli_list_t *
writeAtom(to, atom);
}
-gboolean aac_can_handle_file(VFSFile *f) {
+gboolean aac_can_handle_file(VFSFile * f)
+{
Atom *first_atom = readAtom(f);
+ if (first_atom == NULL)
+ return FALSE;
if (!strcmp(first_atom->name, FTYP))
return TRUE;
return FALSE;
}
-Tuple *aac_populate_tuple_from_file(Tuple *tuple, VFSFile *f) {
+gboolean aac_read_tag (Tuple * tuple, VFSFile * f)
+{
if (ilstAtom)
g_free(ilstAtom);
ilstAtom = getilstAtom(f);
@@ -216,7 +253,8 @@ Tuple *aac_populate_tuple_from_file(Tuple *tuple, VFSFile *f) {
{
mowgli_node_t *n, *tn;
- MOWGLI_LIST_FOREACH_SAFE(n, tn, dataAtoms->head) {
+ MOWGLI_LIST_FOREACH_SAFE(n, tn, dataAtoms->head)
+ {
mowgli_node_delete(n, dataAtoms);
}
}
@@ -239,55 +277,57 @@ Tuple *aac_populate_tuple_from_file(Tuple *tuple, VFSFile *f) {
switch (atomtype)
{
- case MP4_ALBUM:
- {
- tuple_associate_string(tuple, FIELD_ALBUM, NULL, a->data);
- }
- break;
- case MP4_TITLE:
- {
- tuple_associate_string(tuple, FIELD_TITLE, NULL, a->data);
- }
- break;
- case MP4_COPYRIGHT:
- {
- tuple_associate_string(tuple, FIELD_COPYRIGHT, NULL, a->data);
- }
- break;
- case MP4_ARTIST:
- case MP4_ARTIST2:
- {
- tuple_associate_string(tuple, FIELD_ARTIST, NULL, a->data);
- }
- break;
- case MP4_TRACKNR:
- {
- //tuple_associate_string(tuple,FIELD_ALBUM,NULL,a->data);
- }
- break;
- case MP4_YEAR:
- {
- tuple_associate_int(tuple, FIELD_YEAR, NULL, atoi(a->data));
- }
- break;
- case MP4_GENRE:
- {
- guint8 *val = (guint8*) (a->data + (a->datasize - 17));
- const gchar* genre = ID3v1GenreList[*val - 1];
- tuple_associate_string(tuple, FIELD_GENRE, NULL, genre);
- }
- break;
- case MP4_COMMENT:
- {
- tuple_associate_string(tuple, FIELD_COMMENT, NULL, a->data);
- }
- break;
+ case MP4_ALBUM:
+ {
+ tuple_associate_string(tuple, FIELD_ALBUM, NULL, a->data);
+ }
+ break;
+ case MP4_TITLE:
+ {
+ tuple_associate_string(tuple, FIELD_TITLE, NULL, a->data);
+ }
+ break;
+ case MP4_COPYRIGHT:
+ {
+ tuple_associate_string(tuple, FIELD_COPYRIGHT, NULL, a->data);
+ }
+ break;
+ case MP4_ARTIST:
+ case MP4_ARTIST2:
+ {
+ tuple_associate_string(tuple, FIELD_ARTIST, NULL, a->data);
+ }
+ break;
+ case MP4_TRACKNR:
+ {
+ //tuple_associate_string(tuple,FIELD_ALBUM,NULL,a->data);
+ }
+ break;
+ case MP4_YEAR:
+ {
+ tuple_associate_int(tuple, FIELD_YEAR, NULL, atoi(a->data));
+ }
+ break;
+ case MP4_GENRE:
+ {
+ guint8 *val = (guint8 *) (a->data + (a->datasize - 17));
+ const gchar *genre = ID3v1GenreList[*val - 1];
+ tuple_associate_string(tuple, FIELD_GENRE, NULL, genre);
+ }
+ break;
+ case MP4_COMMENT:
+ {
+ tuple_associate_string(tuple, FIELD_COMMENT, NULL, a->data);
+ }
+ break;
}
}
- return tuple;
+
+ return TRUE;
}
-gboolean aac_write_tuple_to_file(Tuple* tuple, VFSFile *f) {
+gboolean aac_write_tag (Tuple * tuple, VFSFile * f)
+{
#ifdef BROKEN
return FALSE;
#endif
@@ -296,129 +336,136 @@ gboolean aac_write_tuple_to_file(Tuple* tuple, VFSFile *f) {
mowgli_list_t *newdataAtoms;
newdataAtoms = mowgli_list_create();
- MOWGLI_LIST_FOREACH_SAFE(n, tn, dataAtoms->head) {
- int atomtype = getAtomID(((StrDataAtom*) (n->data))->name);
+ MOWGLI_LIST_FOREACH_SAFE(n, tn, dataAtoms->head)
+ {
+ int atomtype = getAtomID(((StrDataAtom *) (n->data))->name);
switch (atomtype)
{
- case MP4_ALBUM:
- {
- const gchar* strVal = tuple_get_string(tuple, FIELD_ALBUM, NULL);
- if (strVal != NULL)
- {
- StrDataAtom *atom = g_new0(StrDataAtom, 1);
- atom = makeAtomWithData(strVal, atom, MP4_ALBUM);
- mowgli_node_add(atom, mowgli_node_create(), newdataAtoms);
- newilstSize += atom->atomsize;
- } else
- {
- mowgli_node_add(n->data, mowgli_node_create(), newdataAtoms);
- newilstSize += ((Atom*) (n->data))->size;
- }
- }
- break;
- case MP4_TITLE:
- {
- const gchar* strVal = tuple_get_string(tuple, FIELD_TITLE, NULL);
- if (strVal != NULL)
- {
- StrDataAtom *atom = g_new0(StrDataAtom, 1);
- atom = makeAtomWithData(strVal, atom, MP4_TITLE);
- mowgli_node_add(atom, mowgli_node_create(), newdataAtoms);
- newilstSize += atom->atomsize;
- } else
- {
- mowgli_node_add(n->data, mowgli_node_create(), newdataAtoms);
- newilstSize += ((Atom*) (n->data))->size;
- }
- }
- break;
- case MP4_COPYRIGHT:
- {
- const gchar* strVal = tuple_get_string(tuple, FIELD_COPYRIGHT, NULL);
- if (strVal != NULL)
- {
- StrDataAtom *atom = g_new0(StrDataAtom, 1);
- atom = makeAtomWithData(strVal, atom, MP4_COPYRIGHT);
- mowgli_node_add(atom, mowgli_node_create(), newdataAtoms);
- newilstSize += atom->atomsize;
- } else
- {
- mowgli_node_add(n->data, mowgli_node_create(), newdataAtoms);
- newilstSize += ((Atom*) (n->data))->size;
- }
- }
- break;
- case MP4_ARTIST:
- case MP4_ARTIST2:
- {
- const gchar* strVal = tuple_get_string(tuple, FIELD_ARTIST, NULL);
- if (strVal != NULL)
- {
- StrDataAtom *atom = g_new0(StrDataAtom, 1);
- atom = makeAtomWithData(strVal, atom, MP4_ARTIST2);
- mowgli_node_add(atom, mowgli_node_create(), newdataAtoms);
- newilstSize += atom->atomsize;
- } else
- {
- mowgli_node_add(n->data, mowgli_node_create(), newdataAtoms);
- newilstSize += ((Atom*) (n->data))->size;
- }
- }
- break;
- case MP4_TRACKNR:
- {
- //tuple_associate_string(tuple,FIELD_ALBUM,NULL,a->data);
- }
- break;
- case MP4_YEAR:
- {
- int iyear = tuple_get_int(tuple, FIELD_YEAR, NULL);
- gchar* strVal = g_strdup_printf("%d", iyear);
- if (strVal != NULL)
- {
- StrDataAtom *atom = g_new0(StrDataAtom, 1);
- atom = makeAtomWithData(strVal, atom, MP4_YEAR);
- mowgli_node_add(atom, mowgli_node_create(), newdataAtoms);
- newilstSize += atom->atomsize;
- } else
- {
- mowgli_node_add(n->data, mowgli_node_create(), newdataAtoms);
- newilstSize += ((Atom*) (n->data))->size;
- }
- }
- break;
- /*
- case MP4_GENRE:
- {
-
- guint8 *val = (guint8*)(a->data + (a->datasize-17));
- const gchar* genre = ID3v1GenreList[*val-1];
- tuple_associate_string(tuple,FIELD_GENRE,NULL,genre);
-
- }break;
- */
- case MP4_COMMENT:
- {
- const gchar* strVal = tuple_get_string(tuple, FIELD_COMMENT, NULL);
- if (strVal != NULL)
- {
- StrDataAtom *atom = g_new0(StrDataAtom, 1);
- atom = makeAtomWithData(strVal, atom, MP4_COMMENT);
- mowgli_node_add(atom, mowgli_node_create(), newdataAtoms);
- newilstSize += atom->atomsize;
- } else
- {
- mowgli_node_add(n->data, mowgli_node_create(), newdataAtoms);
- newilstSize += ((Atom*) (n->data))->size;
- }
- }
- break;
- default:
- {
- mowgli_node_add(n->data, mowgli_node_create(), newdataAtoms);
- newilstSize += ((Atom*) (n->data))->size;
- }
- break;
+ case MP4_ALBUM:
+ {
+ const gchar *strVal = tuple_get_string(tuple, FIELD_ALBUM, NULL);
+ if (strVal != NULL)
+ {
+ StrDataAtom *atom = g_new0(StrDataAtom, 1);
+ atom = makeAtomWithData(strVal, atom, MP4_ALBUM);
+ mowgli_node_add(atom, mowgli_node_create(), newdataAtoms);
+ newilstSize += atom->atomsize;
+ }
+ else
+ {
+ mowgli_node_add(n->data, mowgli_node_create(), newdataAtoms);
+ newilstSize += ((Atom *) (n->data))->size;
+ }
+ }
+ break;
+ case MP4_TITLE:
+ {
+ const gchar *strVal = tuple_get_string(tuple, FIELD_TITLE, NULL);
+ if (strVal != NULL)
+ {
+ StrDataAtom *atom = g_new0(StrDataAtom, 1);
+ atom = makeAtomWithData(strVal, atom, MP4_TITLE);
+ mowgli_node_add(atom, mowgli_node_create(), newdataAtoms);
+ newilstSize += atom->atomsize;
+ }
+ else
+ {
+ mowgli_node_add(n->data, mowgli_node_create(), newdataAtoms);
+ newilstSize += ((Atom *) (n->data))->size;
+ }
+ }
+ break;
+ case MP4_COPYRIGHT:
+ {
+ const gchar *strVal = tuple_get_string(tuple, FIELD_COPYRIGHT, NULL);
+ if (strVal != NULL)
+ {
+ StrDataAtom *atom = g_new0(StrDataAtom, 1);
+ atom = makeAtomWithData(strVal, atom, MP4_COPYRIGHT);
+ mowgli_node_add(atom, mowgli_node_create(), newdataAtoms);
+ newilstSize += atom->atomsize;
+ }
+ else
+ {
+ mowgli_node_add(n->data, mowgli_node_create(), newdataAtoms);
+ newilstSize += ((Atom *) (n->data))->size;
+ }
+ }
+ break;
+ case MP4_ARTIST:
+ case MP4_ARTIST2:
+ {
+ const gchar *strVal = tuple_get_string(tuple, FIELD_ARTIST, NULL);
+ if (strVal != NULL)
+ {
+ StrDataAtom *atom = g_new0(StrDataAtom, 1);
+ atom = makeAtomWithData(strVal, atom, MP4_ARTIST2);
+ mowgli_node_add(atom, mowgli_node_create(), newdataAtoms);
+ newilstSize += atom->atomsize;
+ }
+ else
+ {
+ mowgli_node_add(n->data, mowgli_node_create(), newdataAtoms);
+ newilstSize += ((Atom *) (n->data))->size;
+ }
+ }
+ break;
+ case MP4_TRACKNR:
+ {
+ //tuple_associate_string(tuple,FIELD_ALBUM,NULL,a->data);
+ }
+ break;
+ case MP4_YEAR:
+ {
+ int iyear = tuple_get_int(tuple, FIELD_YEAR, NULL);
+ gchar *strVal = g_strdup_printf("%d", iyear);
+ if (strVal != NULL)
+ {
+ StrDataAtom *atom = g_new0(StrDataAtom, 1);
+ atom = makeAtomWithData(strVal, atom, MP4_YEAR);
+ mowgli_node_add(atom, mowgli_node_create(), newdataAtoms);
+ newilstSize += atom->atomsize;
+ }
+ else
+ {
+ mowgli_node_add(n->data, mowgli_node_create(), newdataAtoms);
+ newilstSize += ((Atom *) (n->data))->size;
+ }
+ }
+ break;
+ /*
+ case MP4_GENRE:
+ {
+
+ guint8 *val = (guint8*)(a->data + (a->datasize-17));
+ const gchar* genre = ID3v1GenreList[*val-1];
+ tuple_associate_string(tuple,FIELD_GENRE,NULL,genre);
+
+ }break;
+ */
+ case MP4_COMMENT:
+ {
+ const gchar *strVal = tuple_get_string(tuple, FIELD_COMMENT, NULL);
+ if (strVal != NULL)
+ {
+ StrDataAtom *atom = g_new0(StrDataAtom, 1);
+ atom = makeAtomWithData(strVal, atom, MP4_COMMENT);
+ mowgli_node_add(atom, mowgli_node_create(), newdataAtoms);
+ newilstSize += atom->atomsize;
+ }
+ else
+ {
+ mowgli_node_add(n->data, mowgli_node_create(), newdataAtoms);
+ newilstSize += ((Atom *) (n->data))->size;
+ }
+ }
+ break;
+ default:
+ {
+ mowgli_node_add(n->data, mowgli_node_create(), newdataAtoms);
+ newilstSize += ((Atom *) (n->data))->size;
+ }
+ break;
}
}
diff --git a/src/libaudtag/aac/aac.h b/src/libaudtag/aac/aac.h
index 7d2d1f2..8f4d57d 100644
--- a/src/libaudtag/aac/aac.h
+++ b/src/libaudtag/aac/aac.h
@@ -1,3 +1,23 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
#ifndef AAC_H
#define AAC_H
#include <libaudcore/tuple.h>
@@ -46,21 +66,21 @@ typedef struct strdataatom
int type;
}StrDataAtom;
-
-
-gboolean aac_can_handle_file(VFSFile *f);
-
-Tuple *aac_populate_tuple_from_file(Tuple *tuple,VFSFile *f);
-
-gboolean aac_write_tuple_to_file(Tuple* tuple, VFSFile *f);
-
-extern tag_module_t aac;
-
Atom *ilstAtom;
guint64 ilstFileOffset;
guint32 newilstSize ;
mowgli_list_t *dataAtoms;
mowgli_dictionary_t *ilstAtoms;
-#endif
+/* TAG plugin API */
+gboolean aac_can_handle_file(VFSFile *f);
+gboolean aac_read_tag (Tuple * tuple, VFSFile * handle);
+gboolean aac_write_tag (Tuple * tuple, VFSFile * handle);
+static const tag_module_t aac = {
+ .name = "AAC",
+ .can_handle_file = aac_can_handle_file,
+ .read_tag = aac_read_tag,
+ .write_tag = aac_write_tag,
+};
+#endif
diff --git a/src/libaudtag/ape/ape.c b/src/libaudtag/ape/ape.c
index 46d45cc..548ac92 100755
--- a/src/libaudtag/ape/ape.c
+++ b/src/libaudtag/ape/ape.c
@@ -1,298 +1,505 @@
+/*
+ * Copyright 2010 John Lindgren
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+/* TODO:
+ * - Support updating files that have their tag at the beginning?
+ */
+
#include <glib.h>
-#include <glib/gstdio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libaudcore/vfs.h>
+
#include "ape.h"
-#include "../util.h"
-#include <inttypes.h>
-#include "../tag_module.h"
-#define APE_IDENTIFIER "APETAGEX"
+#pragma pack(push) /* must be byte-aligned */
+#pragma pack(1)
+typedef struct
+{
+ gchar magic[8];
+ guint32 version; /* LE */
+ guint32 length; /* LE */
+ guint32 items; /* LE */
+ guint32 flags; /* LE */
+ guint64 reserved;
+}
+APEHeader;
+#pragma pack(pop)
-tag_module_t ape = {ape_can_handle_file, ape_populate_tuple_from_file, ape_write_tuple_to_file};
+typedef struct
+{
+ gchar * key, * value;
+}
+ValuePair;
-gchar* ape_items[] = {"Album", "Title", "Copyright", "Artist", "Track", "Year", "Genre", "Comment"};
+#define APE_FLAG_HAS_HEADER (1 << 31)
+#define APE_FLAG_HAS_NO_FOOTER (1 << 30)
+#define APE_FLAG_IS_HEADER (1 << 29)
-/* reading fucntions */
+static gboolean ape_read_header (VFSFile * handle, APEHeader * header)
+{
+ if (vfs_fread (header, 1, sizeof (APEHeader), handle) != sizeof (APEHeader))
+ return FALSE;
+ if (strncmp (header->magic, "APETAGEX", 8))
+ return FALSE;
-APEv2Header *readAPEHeader(VFSFile *fd) {
- APEv2Header *header = g_new0(APEv2Header, 1);
- header->preamble = read_char_data(fd, 8);
- header->version = read_LEuint32(fd);
- header->tagSize = read_LEuint32(fd);
- header->itemCount = read_LEuint32(fd);
- header->reserved = read_LEuint64(fd);
- return header;
-}
+ header->version = GUINT32_FROM_LE (header->version);
+ header->length = GUINT32_FROM_LE (header->length);
+ header->items = GUINT32_FROM_LE (header->items);
+ header->flags = GUINT32_FROM_LE (header->flags);
-gchar* read_NULLterminatedString(VFSFile *fd) {
- gchar buf[1024];
- gchar ch;
- int size = 0;
- while (1) {
- vfs_fread(&ch, 1, 1, fd);
- if (ch != 0) {
- buf[size] = ch;
- size++;
- } else
- break;
- }
- gchar* ret = g_strndup(buf, size);
+ if (header->length < sizeof (APEHeader))
+ return FALSE;
- return ret;
+ return TRUE;
}
-gchar* readUTF_8(VFSFile *fd, int size) {
- gchar *buf = g_new0(gchar, size);
- vfs_fread(buf, size, 1, fd);
- return buf;
-}
+static gboolean ape_find_header (VFSFile * handle, APEHeader * header, gint *
+ start, gint * length, gint * data_start, gint * data_length)
+{
+ APEHeader secondary;
-APETagItem *readAPETagItem(VFSFile *fd) {
- APETagItem *tagitem = g_new0(APETagItem, 1);
- tagitem->size = read_LEuint32(fd);
- tagitem->flags = read_LEuint32(fd);
- tagitem->key = read_NULLterminatedString(fd);
- tagitem->value = readUTF_8(fd, tagitem->size);
+ if (vfs_fseek (handle, 0, SEEK_SET))
+ return FALSE;
- return tagitem;
-}
+ if (ape_read_header (handle, header))
+ {
+ AUDDBG ("Found header at 0, length = %d, version = %d.\n", (gint)
+ header->length, (gint) header->version);
+ * start = 0;
+ * length = header->length;
+ * data_start = sizeof (APEHeader);
+ * data_length = header->length - sizeof (APEHeader);
+
+ if (! (header->flags & APE_FLAG_HAS_HEADER) || ! (header->flags &
+ APE_FLAG_IS_HEADER))
+ {
+ AUDDBG ("Invalid header flags (%u).\n", (guint) header->flags);
+ return FALSE;
+ }
+
+ if (! (header->flags & APE_FLAG_HAS_NO_FOOTER))
+ {
+ if (vfs_fseek (handle, header->length, SEEK_CUR))
+ return FALSE;
+
+ if (! ape_read_header (handle, & secondary))
+ {
+ AUDDBG ("Expected footer, but found none.\n");
+ return FALSE;
+ }
+
+ * length += sizeof (APEHeader);
+ }
+
+ return TRUE;
+ }
-//writing functions
+ if (vfs_fseek (handle, -sizeof (APEHeader), SEEK_END))
+ return FALSE;
-void write_tagItemToFile(VFSFile *fd, APETagItem *item) {
- item->size -=1;
- vfs_fwrite(&item->size, 4, 1, fd);
- vfs_fwrite(&item->flags, 4, 1, fd);
- vfs_fwrite(item->key, strlen(item->key) +1, 1, fd);
- vfs_fwrite(item->value, item->size, 1, fd);
+ if (ape_read_header (handle, header))
+ {
+ AUDDBG ("Found footer at %d, length = %d, version = %d.\n", (gint)
+ vfs_ftell (handle) - (gint) sizeof (APEHeader), (gint) header->length,
+ (gint) header->version);
+ * start = vfs_ftell (handle) - header->length;
+ * length = header->length;
+ * data_start = vfs_ftell (handle) - header->length;
+ * data_length = header->length - sizeof (APEHeader);
+
+ if ((header->flags & APE_FLAG_HAS_NO_FOOTER) || (header->flags &
+ APE_FLAG_IS_HEADER))
+ {
+ AUDDBG ("Invalid footer flags (%u).\n", (guint) header->flags);
+ return FALSE;
+ }
+
+ if (header->flags & APE_FLAG_HAS_HEADER)
+ {
+ if (vfs_fseek (handle, -(gint) header->length - sizeof (APEHeader),
+ SEEK_CUR))
+ return FALSE;
+
+ if (! ape_read_header (handle, & secondary))
+ {
+ AUDDBG ("Expected header, but found none.\n");
+ return FALSE;
+ }
+
+ * start -= sizeof (APEHeader);
+ * length += sizeof (APEHeader);
+ }
+
+ return TRUE;
+ }
+
+ AUDDBG ("No header found.\n");
+ return FALSE;
}
-void write_apeHeaderToFile(VFSFile *fd, APEv2Header *header) {
- vfs_fwrite(header->preamble, 8, 1, fd);
- vfs_fwrite(&header->version, 4, 1, fd);
- vfs_fwrite(&header->tagSize, 4, 1, fd);
- vfs_fwrite(&header->itemCount, 4, 1, fd);
- vfs_fwrite(&header->flags, 4, 1, fd);
- vfs_fwrite(&header->reserved, 8, 1, fd);
+static gboolean ape_is_our_file (VFSFile * handle)
+{
+ APEHeader header;
+ gint start, length, data_start, data_length;
+
+ return ape_find_header (handle, & header, & start, & length, & data_start,
+ & data_length);
}
-void write_allTagsToFile(VFSFile *fd, APEv2Header *header) {
- mowgli_node_t *n, *tn;
+static ValuePair * ape_read_item (void * * data, gint length)
+{
+ guint32 * header = * data;
+ gchar * value;
+ ValuePair * pair;
- MOWGLI_LIST_FOREACH_SAFE(n, tn, tagKeys->head) {
- APETagItem *tagItem = (APETagItem*) mowgli_dictionary_retrieve(tagItems, (gchar*) (n->data));
- write_tagItemToFile(fd, tagItem);
+ if (length < 8)
+ {
+ AUDDBG ("Expected item, but only %d bytes remain in tag.\n", length);
+ return NULL;
}
-}
-APEv2Header *computeNewHeader() {
- guint32 size = 0;
- mowgli_node_t *n, *tn;
- APEv2Header *header = g_new0(APEv2Header, 1);
+ value = memchr ((gchar *) (* data) + 8, 0, length - 8);
- MOWGLI_LIST_FOREACH_SAFE(n, tn, tagKeys->head) {
- APETagItem *tagItem = (APETagItem*) mowgli_dictionary_retrieve(tagItems, (gchar*) (n->data));
- size += (tagItem->size + 4 + 4 + strlen(tagItem->key));
+ if (value == NULL)
+ {
+ AUDDBG ("Unterminated item key (max length = %d).\n", length - 8);
+ return NULL;
}
- header->flags = 0;
- header->preamble = APE_IDENTIFIER;
- header->reserved = 0;
- header->version = 2000;
- header->itemCount = tagKeys->count;
- header->tagSize = size + 32 ; //(32 - the size of the footer)
-
- return header;
-}
-int getTagItemID(APETagItem *tagitem) {
- int i = 0;
- for (i = 0; i < APE_ITEMS_NO; i++) {
- if (!g_utf8_collate(tagitem->key, ape_items[i]))
- return i;
+ value ++;
+
+ if (header[0] > (gchar *) (* data) + length - value)
+ {
+ AUDDBG ("Item value of length %d, but only %d bytes remain in tag.\n",
+ (gint) header[0], (gint) ((gchar *) (* data) + length - value));
+ return NULL;
}
- return -1;
-}
-gboolean tagContainsHeader(APEv2Header *header) {
- return (header->flags & 0x0001);
+ pair = g_malloc (sizeof (ValuePair));
+ pair->key = g_strdup ((gchar *) (* data) + 8);
+ pair->value = g_strndup (value, header[0]);
+
+ * data = value + header[0];
+
+ return pair;
}
-void add_tagItemFromTuple(Tuple *tuple, int tuple_field, int ape_field) {
- gboolean new = FALSE;
- APETagItem *tagItem = (APETagItem*) mowgli_dictionary_retrieve(tagItems, ape_items[ape_field]);
- if (tagItem == NULL) {
- tagItem = g_new0(APETagItem, 1);
- new = TRUE;
+static GList * ape_read_items (VFSFile * handle)
+{
+ GList * list = NULL;
+ APEHeader header;
+ gint start, length, data_start, data_length;
+ void * data, * item;
+
+ if (! ape_find_header (handle, & header, & start, & length, & data_start,
+ & data_length))
+ return NULL;
+
+ if (vfs_fseek (handle, data_start, SEEK_SET))
+ return NULL;
+
+ data = g_malloc (data_length);
+
+ if (vfs_fread (data, 1, data_length, handle) != data_length)
+ {
+ g_free (data);
+ return NULL;
+ }
+
+ AUDDBG ("Reading %d items:\n", header.items);
+ item = data;
+
+ while (header.items --)
+ {
+ ValuePair * pair = ape_read_item (& item, (gchar *) data + data_length -
+ (gchar *) item);
+
+ if (pair == NULL)
+ break;
+
+ AUDDBG ("Read: %s = %s.\n", pair->key, pair->value);
+ list = g_list_prepend (list, pair);
}
- gchar* value = 0;
- if (tuple_get_value_type(tuple, tuple_field, NULL) == TUPLE_STRING)
- value = g_strdup(tuple_get_string(tuple, tuple_field, NULL));
- if (tuple_get_value_type(tuple, tuple_field, NULL) == TUPLE_INT)
- value = g_strdup_printf("%d", tuple_get_int(tuple, tuple_field, NULL));
-
- tagItem->flags = 0;
- tagItem->key = g_strdup(ape_items[ape_field]);
- tagItem->value = value;
- tagItem->size = strlen(value) + 1;
- if (new) {
- mowgli_node_add(tagItem->key, mowgli_node_create(), tagKeys);
- mowgli_dictionary_add(tagItems, tagItem->key, tagItem);
+
+ g_free (data);
+ return g_list_reverse (list);
+}
+
+static void free_tag_list (GList * list)
+{
+ while (list != NULL)
+ {
+ g_free (((ValuePair *) list->data)->key);
+ g_free (((ValuePair *) list->data)->value);
+ g_free (list->data);
+ list = g_list_delete_link (list, list);
}
}
+static void parse_gain_text (const gchar * text, gint * value, gint * unit)
+{
+ gint sign = 1;
+ * value = 0;
+ * unit = 1;
-gboolean ape_can_handle_file(VFSFile *f) {
- APEv2Header *header = readAPEHeader(f);
- if (!strcmp(header->preamble, APE_IDENTIFIER))
- return TRUE;
- else {
- //maybe the tag is at the end of the file
- guint64 filesize = vfs_fsize(f);
- vfs_fseek(f, filesize-32, SEEK_SET);
- APEv2Header *header = readAPEHeader(f);
- if (!strcmp(header->preamble, APE_IDENTIFIER))
- return TRUE;
+ if (* text == '-')
+ {
+ sign = -1;
+ text ++;
}
- return FALSE;
-}
-Tuple *ape_populate_tuple_from_file(Tuple *tuple, VFSFile *f) {
- int i;
- vfs_fseek(f, 0, SEEK_SET);
- headerPosition = 0;
- guint64 filesize = vfs_fsize(f);
- APEv2Header *header = readAPEHeader(f);
- if (strcmp(header->preamble, APE_IDENTIFIER)) {
- g_free(header);
- //maybe the tag is at the end of the file
- vfs_fseek(f, filesize-32, SEEK_SET);
- header = readAPEHeader(f);
- if (!strcmp(header->preamble, APE_IDENTIFIER)) {
- //read all the items from the end of the file
- // if(tagContainsHeader(header))
- gchar* path = g_strdup(f->uri);
- vfs_fclose(f);
- f = vfs_fopen(path,"r");
- long offset = filesize - (header->tagSize);
- vfs_fseek(f, offset, SEEK_SET);
- headerPosition = vfs_ftell(f);
- // else vfs_fseek(f,-(header->tagSize),SEEK_END);
- } else
- return NULL;
- } else
- return NULL;
- if(tagKeys != NULL)
+ while (* text >= '0' && * text <= '9')
+ {
+ * value = * value * 10 + (* text - '0');
+ text ++;
+ }
+
+ if (* text == '.')
{
- mowgli_node_t *n, *tn;
- MOWGLI_LIST_FOREACH_SAFE(n, tn, tagKeys->head)
+ text ++;
+
+ while (* text >= '0' && * text <= '9' && * value < G_MAXINT / 10)
{
- mowgli_node_delete(n,tagKeys);
+ * value = * value * 10 + (* text - '0');
+ * unit = * unit * 10;
+ text ++;
}
}
- tagKeys = mowgli_list_create();
- tagItems = mowgli_dictionary_create(strcasecmp);
- for (i = 0; i < header->itemCount; i++) {
- APETagItem *tagitem = readAPETagItem(f);
- int tagid = getTagItemID(tagitem);
- mowgli_node_add(tagitem->key, mowgli_node_create(), tagKeys);
- mowgli_dictionary_add(tagItems, tagitem->key, tagitem);
-
- switch (tagid) {
- case APE_ALBUM:
- {
- tuple_associate_string(tuple, FIELD_ALBUM, NULL, tagitem->value);
- }
- break;
- case APE_TITLE:
- {
- tuple_associate_string(tuple, FIELD_TITLE, NULL, tagitem->value);
- }
- break;
- case APE_COPYRIGHT:
- {
- tuple_associate_string(tuple, FIELD_COPYRIGHT, NULL, tagitem->value);
- }
- break;
- case APE_ARTIST:
- {
- tuple_associate_string(tuple, FIELD_ARTIST, NULL, tagitem->value);
- }
- break;
- case APE_TRACKNR:
- {
- tuple_associate_int(tuple, FIELD_TRACK_NUMBER, NULL, atoi(tagitem->value));
- }
- break;
- case APE_YEAR:
- {
- tuple_associate_int(tuple, FIELD_YEAR, NULL, atoi(tagitem->value));
- }
- break;
- case APE_GENRE:
- {
- tuple_associate_string(tuple, FIELD_GENRE, NULL, tagitem->value);
- }
- break;
- case APE_COMMENT:
- {
- tuple_associate_string(tuple, FIELD_COMMENT, NULL, tagitem->value);
- }
- break;
- }
+ * value = * value * sign;
+}
+
+static void set_gain_info (Tuple * tuple, gint field, gint unit_field,
+ const gchar * text)
+{
+ gint value, unit;
+
+ parse_gain_text (text, & value, & unit);
+
+ if (tuple_get_value_type (tuple, unit_field, NULL) == TUPLE_INT)
+ value = value * (gint64) tuple_get_int (tuple, unit_field, NULL) / unit;
+ else
+ tuple_associate_int (tuple, unit_field, NULL, unit);
+
+ tuple_associate_int (tuple, field, NULL, value);
+}
+
+static gboolean ape_read_tag (Tuple * tuple, VFSFile * handle)
+{
+ GList * list = ape_read_items (handle), * node;
+
+ for (node = list; node != NULL; node = node->next)
+ {
+ gchar * key = ((ValuePair *) node->data)->key;
+ gchar * value = ((ValuePair *) node->data)->value;
+
+ if (! strcmp (key, "Artist"))
+ tuple_associate_string (tuple, FIELD_ARTIST, NULL, value);
+ else if (! strcmp (key, "Title"))
+ tuple_associate_string (tuple, FIELD_TITLE, NULL, value);
+ else if (! strcmp (key, "Album"))
+ tuple_associate_string (tuple, FIELD_ALBUM, NULL, value);
+ else if (! strcmp (key, "Comment"))
+ tuple_associate_string (tuple, FIELD_COMMENT, NULL, value);
+ else if (! strcmp (key, "Genre"))
+ tuple_associate_string (tuple, FIELD_GENRE, NULL, value);
+ else if (! strcmp (key, "Track"))
+ tuple_associate_int (tuple, FIELD_TRACK_NUMBER, NULL, atoi (value));
+ else if (! strcmp (key, "Year"))
+ tuple_associate_int (tuple, FIELD_YEAR, NULL, atoi (value));
+ else if (! strcasecmp (key, "REPLAYGAIN_TRACK_GAIN"))
+ set_gain_info (tuple, FIELD_GAIN_TRACK_GAIN, FIELD_GAIN_GAIN_UNIT,
+ value);
+ else if (! strcasecmp (key, "REPLAYGAIN_TRACK_PEAK"))
+ set_gain_info (tuple, FIELD_GAIN_TRACK_PEAK, FIELD_GAIN_PEAK_UNIT,
+ value);
+ else if (! strcasecmp (key, "REPLAYGAIN_ALBUM_GAIN"))
+ set_gain_info (tuple, FIELD_GAIN_ALBUM_GAIN, FIELD_GAIN_GAIN_UNIT,
+ value);
+ else if (! strcasecmp (key, "REPLAYGAIN_ALBUM_PEAK"))
+ set_gain_info (tuple, FIELD_GAIN_ALBUM_PEAK, FIELD_GAIN_PEAK_UNIT,
+ value);
}
- return tuple;
+
+ free_tag_list (list);
+ return TRUE;
}
-gboolean ape_write_tuple_to_file(Tuple* tuple, VFSFile *f)
+static gboolean ape_write_item (VFSFile * handle, const gchar * key,
+ const gchar * value, int * written_length)
{
- VFSFile *tmp;
- const gchar *tmpdir = g_get_tmp_dir();
- gchar *tmp_path = g_strdup_printf("file://%s/%s", tmpdir, "tmp.mpc");
- tmp = vfs_fopen(tmp_path, "w+");
+ gint key_len = strlen (key) + 1;
+ gint value_len = strlen (value);
+ guint32 header[2];
+ AUDDBG ("Write: %s = %s.\n", key, value);
- if (tuple_get_string(tuple, FIELD_ARTIST, NULL))
- add_tagItemFromTuple(tuple, FIELD_ARTIST, APE_ARTIST);
+ header[0] = GUINT32_TO_LE (value_len);
+ header[1] = 0;
- if (tuple_get_string(tuple, FIELD_TITLE, NULL))
- add_tagItemFromTuple(tuple, FIELD_TITLE, APE_TITLE);
+ if (vfs_fwrite (header, 1, 8, handle) != 8)
+ return FALSE;
+ if (vfs_fwrite (key, 1, key_len, handle) != key_len)
+ return FALSE;
- if (tuple_get_string(tuple, FIELD_ALBUM, NULL))
- add_tagItemFromTuple(tuple, FIELD_ALBUM, APE_ALBUM);
+ if (vfs_fwrite (value, 1, value_len, handle) != value_len)
+ return FALSE;
- if (tuple_get_string(tuple, FIELD_COMMENT, NULL))
- add_tagItemFromTuple(tuple, FIELD_COMMENT, APE_COMMENT);
+ * written_length += 8 + key_len + value_len;
+ return TRUE;
+}
- if (tuple_get_string(tuple, FIELD_GENRE, NULL))
- add_tagItemFromTuple(tuple, FIELD_GENRE, APE_GENRE);
+static gboolean write_string_item (Tuple * tuple, int field, VFSFile * handle,
+ const gchar * key, int * written_length, int * written_items)
+{
+ const gchar * value = tuple_get_string (tuple, field, NULL);
- if (tuple_get_int(tuple, FIELD_YEAR, NULL) != -1)
- add_tagItemFromTuple(tuple, FIELD_YEAR, APE_YEAR);
+ if (value == NULL)
+ return TRUE;
- if(tuple_get_int(tuple,FIELD_TRACK_NUMBER,NULL) != -1)
- add_tagItemFromTuple(tuple, FIELD_TRACK_NUMBER, APE_TRACKNR);
+ if (! ape_write_item (handle, key, value, written_length))
+ return FALSE;
- copyAudioData(f,tmp,0,headerPosition);
+ (* written_items) ++;
+ return TRUE;
+}
- APEv2Header *header = computeNewHeader();
- write_apeHeaderToFile(tmp, header);
+static gboolean write_integer_item (Tuple * tuple, int field, VFSFile * handle,
+ const gchar * key, int * written_length, int * written_items)
+{
+ gint value = tuple_get_int (tuple, field, NULL);
+ gchar scratch[32];
- write_allTagsToFile(tmp, header);
- write_apeHeaderToFile(tmp, header);
+ if (! value)
+ return TRUE;
+ snprintf (scratch, sizeof scratch, "%d", value);
- gchar *uri = g_strdup(f -> uri);
- vfs_fclose(tmp);
- gchar* f1 = g_filename_from_uri(tmp_path,NULL,NULL);
- gchar* f2 = g_filename_from_uri(uri,NULL,NULL);
- if (g_rename(f1,f2 ) == 0) {
- AUDDBG("the tag was updated successfully\n");
- } else {
- AUDDBG("an error has occured\n");
+ if (! ape_write_item (handle, key, scratch, written_length))
+ return FALSE;
+
+ (* written_items) ++;
+ return TRUE;
+}
+
+static gboolean write_header (gint data_length, gint items, gboolean is_header,
+ VFSFile * handle)
+{
+ APEHeader header;
+
+ memcpy (header.magic, "APETAGEX", 8);
+ header.version = GUINT32_TO_LE (2000);
+ header.length = GUINT32_TO_LE (data_length + sizeof (APEHeader));
+ header.items = GUINT32_TO_LE (items);
+ header.flags = is_header ? GUINT32_TO_LE (APE_FLAG_HAS_HEADER |
+ APE_FLAG_IS_HEADER) : GUINT32_TO_LE (APE_FLAG_HAS_HEADER);
+ header.reserved = 0;
+
+ return vfs_fwrite (& header, 1, sizeof (APEHeader), handle) == sizeof
+ (APEHeader);
+}
+
+static gboolean ape_write_tag (Tuple * tuple, VFSFile * handle)
+{
+ GList * list = ape_read_items (handle), * node;
+ APEHeader header;
+ gint start, length, data_start, data_length, items;
+
+ if (ape_find_header (handle, & header, & start, & length, & data_start,
+ & data_length))
+ {
+ if (start + length != vfs_fsize (handle))
+ {
+ AUDDBG ("Writing tags is only supported at end of file.\n");
+ goto ERROR;
+ }
+
+ if (vfs_ftruncate (handle, start))
+ goto ERROR;
+ }
+ else
+ {
+ start = vfs_fsize (handle);
+
+ if (start < 0)
+ goto ERROR;
+ }
+
+ if (vfs_fseek (handle, start, SEEK_SET) || ! write_header (0, 0, TRUE,
+ handle))
+ goto ERROR;
+
+ length = 0;
+ items = 0;
+
+ if (! write_string_item (tuple, FIELD_ARTIST, handle, "Artist", & length,
+ & items) || ! write_string_item (tuple, FIELD_TITLE, handle, "Title",
+ & length, & items) || ! write_string_item (tuple, FIELD_ALBUM, handle,
+ "Album", & length, & items) || ! write_string_item (tuple, FIELD_COMMENT,
+ handle, "Comment", & length, & items) || ! write_string_item (tuple,
+ FIELD_GENRE, handle, "Genre", & length, & items) || ! write_integer_item
+ (tuple, FIELD_TRACK_NUMBER, handle, "Track", & length, & items) ||
+ ! write_integer_item (tuple, FIELD_YEAR, handle, "Year", & length, & items))
+ goto ERROR;
+
+ for (node = list; node != NULL; node = node->next)
+ {
+ gchar * key = ((ValuePair *) node->data)->key;
+ gchar * value = ((ValuePair *) node->data)->value;
+
+ if (! strcmp (key, "Artist") || ! strcmp (key, "Title") || ! strcmp
+ (key, "Album") || ! strcmp (key, "Comment") || ! strcmp (key, "Genre")
+ || ! strcmp (key, "Track") || ! strcmp (key, "Year"))
+ continue;
+
+ if (! ape_write_item (handle, key, value, & length))
+ goto ERROR;
+
+ items ++;
}
- //skip the tag at the end - add the new tag
+
+ AUDDBG ("Wrote %d items, %d bytes.\n", items, length);
+
+ if (! write_header (length, items, FALSE, handle) || vfs_fseek (handle,
+ start, SEEK_SET) || ! write_header (length, items, TRUE, handle))
+ goto ERROR;
+
+ free_tag_list (list);
return TRUE;
+
+ERROR:
+ free_tag_list (list);
+ return FALSE;
}
+
+tag_module_t ape =
+{
+ .name = "APE",
+ .type = TAG_TYPE_APE,
+ .can_handle_file = ape_is_our_file,
+ .read_tag = ape_read_tag,
+ .write_tag = ape_write_tag,
+};
diff --git a/src/libaudtag/ape/ape.h b/src/libaudtag/ape/ape.h
index 2ac0f3a..67f6830 100644
--- a/src/libaudtag/ape/ape.h
+++ b/src/libaudtag/ape/ape.h
@@ -1,52 +1,30 @@
-#ifndef APE_H
-
-#define APE_H
-
-#include <libaudcore/tuple.h>
-#include <libaudcore/vfs.h>
+/*
+ * Copyright 2010 John Lindgren
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+#ifndef AUDTAG_APE_H
+#define AUDTAG_APE_H
+
+#include "../audtag.h"
#include "../tag_module.h"
-
-enum {
- APE_ALBUM = 0,
- APE_TITLE,
- APE_COPYRIGHT,
- APE_ARTIST,
- APE_TRACKNR,
- APE_YEAR,
- APE_GENRE,
- APE_COMMENT,
- APE_ITEMS_NO
-};
-
-
-
-typedef struct apeheader
-{
- gchar *preamble; //64 bits
- guint32 version;
- guint32 tagSize;
- guint32 itemCount;
- guint32 flags;
- guint64 reserved;
-}APEv2Header;
-
-typedef struct tagitem
-{
- guint32 size;
- guint32 flags;
- gchar* key; //null terminated
- gchar* value;
-}APETagItem;
-
-gboolean ape_can_handle_file(VFSFile *f);
-
-Tuple *ape_populate_tuple_from_file(Tuple *tuple,VFSFile *f);
-
-gboolean ape_write_tuple_to_file(Tuple* tuple, VFSFile *f);
+#include "../util.h"
extern tag_module_t ape;
-mowgli_dictionary_t *tagItems;
-mowgli_list_t *tagKeys;
-guint32 headerPosition ;
#endif
diff --git a/src/libaudtag/audtag.c b/src/libaudtag/audtag.c
index 3ad1e11..6813798 100644
--- a/src/libaudtag/audtag.c
+++ b/src/libaudtag/audtag.c
@@ -1,25 +1,67 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
#include "libaudcore/tuple.h"
#include "audtag.h"
#include "tag_module.h"
#include "util.h"
-void tag_init(void) {
+void tag_init(void)
+{
init_tag_modules();
}
/* The tuple's file-related attributes are already set */
-Tuple *tag_tuple_read(Tuple *tuple,VFSFile *fd) {
- tag_module_t *mod = find_tag_module(fd);
- g_return_val_if_fail(mod != NULL, NULL);
- AUDDBG("OK\n");
- return mod->populate_tuple_from_file(tuple,fd);
+gboolean tag_tuple_read (Tuple * tuple, VFSFile * handle)
+{
+ tag_module_t * module = find_tag_module (handle, TAG_TYPE_NONE);
+
+ if (module == NULL)
+ return FALSE;
+
+ return module->read_tag (tuple, handle);
+}
+
+gboolean tag_image_read (VFSFile * handle, void * * data, gint * size)
+{
+ tag_module_t * module = find_tag_module (handle, TAG_TYPE_NONE);
+
+ if (module == NULL || module->read_image == NULL)
+ return FALSE;
+
+ return module->read_image (handle, data, size);
}
-gboolean tag_tuple_write_to_file(Tuple *tuple, VFSFile *fd) {
- g_return_val_if_fail((tuple != NULL) && (fd != NULL), FALSE);
- tag_module_t *mod = find_tag_module(fd);
- g_return_val_if_fail(mod != NULL, -1);
+gboolean tag_tuple_write (Tuple * tuple, VFSFile * handle, gint new_type)
+{
+ tag_module_t * module = find_tag_module (handle, new_type);
+
+ if (module == NULL)
+ return FALSE;
+
+ return module->write_tag (tuple, handle);
+}
- return mod->write_tuple_to_file(tuple, fd);
+/* deprecated */
+gboolean tag_tuple_write_to_file (Tuple * tuple, VFSFile * handle)
+{
+ return tag_tuple_write (tuple, handle, TAG_TYPE_NONE);
}
diff --git a/src/libaudtag/audtag.h b/src/libaudtag/audtag.h
index 25089b4..c5338ec 100644
--- a/src/libaudtag/audtag.h
+++ b/src/libaudtag/audtag.h
@@ -1,3 +1,23 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
/* External Interface of the tagging library */
#ifndef AUDTAG_H
@@ -6,18 +26,29 @@
G_BEGIN_DECLS
#include <glib.h>
-#include <mowgli.h>
+#include <mowgli.h>
#include "libaudcore/tuple.h"
#include "libaudcore/vfs.h"
+#include "config.h"
+
+enum
+{
+ TAG_TYPE_NONE = 0,
+ TAG_TYPE_APE,
+};
void tag_init(void);
void tag_terminate(void);
-Tuple *tag_tuple_read(Tuple *tuple, VFSFile *fd);
+gboolean tag_tuple_read (Tuple * tuple, VFSFile *fd);
+gboolean tag_image_read (VFSFile * handle, void * * data, gint * size);
+
+/* new_type specifies the type of tag (see the TAG_TYPE_* enum) that should be
+ * written if the file does not have any existing tag. */
+gboolean tag_tuple_write (Tuple * tuple, VFSFile * handle, gint new_type);
-gboolean tag_tuple_write_to_file(Tuple *tuple, VFSFile *fd);
+/* deprecated, use tag_tuple_write */
+gboolean tag_tuple_write_to_file (Tuple * tuple, VFSFile * handle);
G_END_DECLS
#endif /* AUDTAG_H */
-
-
diff --git a/src/libaudtag/id3/frame.h b/src/libaudtag/id3/frame.h
deleted file mode 100644
index 2cf40c7..0000000
--- a/src/libaudtag/id3/frame.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef AUD_ID3_FRAME
-#define AUD_ID3_FRAME
-
-#include <glib-2.0/glib.h>
-
-enum {
- ID3_ALBUM = 0,
- ID3_TITLE,
- ID3_COMPOSER,
- ID3_COPYRIGHT,
- ID3_DATE,
- ID3_TIME,
- ID3_LENGTH,
- ID3_ARTIST,
- ID3_TRACKNR,
- ID3_YEAR,
- ID3_GENRE,
- ID3_COMMENT,
- ID3_TAGS_NO
-};
-
-char * id3_frames[] = {"TALB","TIT2","TCOM", "TCOP", "TDAT", "TIME", "TLEN", "TPE1", "TRCK", "TYER","TCON", "COMM"};
-
-#endif
diff --git a/src/libaudtag/id3/id3.c b/src/libaudtag/id3/id3.c
deleted file mode 100644
index ed0a131..0000000
--- a/src/libaudtag/id3/id3.c
+++ /dev/null
@@ -1,541 +0,0 @@
-#include <glib.h>
-#include <glib/gstdio.h>
-
-#include "id3.h"
-#include "../util.h"
-#include <inttypes.h>
-#include "../tag_module.h"
-#include "frame.h"
-
-#define TAG_SIZE 1
-
-tag_module_t id3 = {id3_can_handle_file, id3_populate_tuple_from_file, id3_write_tuple_to_file};
-/* reading stuff */
-
-gchar *read_iso8859_1(VFSFile *fd, int size)
-{
- gchar *value= g_new0(gchar,size);
- vfs_fread(value,size,1,fd);
- GError *error = NULL;
- gsize bytes_read = 0 , bytes_write = 0;
- gchar* retVal = g_convert(value,size,"UTF-8","ISO-8859-1",&bytes_read,&bytes_write,&error);
- g_free(value);
- return retVal;
-}
-
-/*
- * Read UTF-16 from the tag and return an uft-8 string for the tuple
- */
-gchar* read_unicode(VFSFile *fd, int size)
-{
- gchar *value= g_new0(gchar,size);
- vfs_fread(value,size,1,fd);
- GError *error = NULL;
- gsize bytes_read = 0 , bytes_write = 0;
- gchar* retVal = g_convert(value,size,"UTF-8","UTF-16",&bytes_read,&bytes_write,&error);
- g_free(value);
- return retVal;
-}
-
-guint32 read_syncsafe_int32(VFSFile *fd)
-{
- guint32 val = read_BEuint32(fd);
- guint32 mask = 0x7f;
- guint32 intVal = 0;
- intVal = ((intVal) | (val & mask));
- int i;
- for(i = 0; i<3; i++)
- {
- mask = mask << 8;
- guint32 tmp = (val & mask);
- tmp = tmp >> 1;
- intVal = intVal | tmp;
- };
- return intVal;
-}
-
-ID3v2Header *readHeader(VFSFile *fd)
-{
- ID3v2Header *header = g_new0(ID3v2Header,1);
- header->id3 = read_char_data(fd,3);
- header->version = read_LEuint16(fd);
- header->flags = *read_char_data(fd,1);
- header->size = read_syncsafe_int32(fd);
- return header;
-}
-
-ExtendedHeader *readExtendedHeader(VFSFile *fd)
-{
- ExtendedHeader *header = g_new0(ExtendedHeader,1);
- header->header_size = read_BEuint32(fd);
- header->flags = read_LEuint16(fd);
- header->padding_size = read_BEuint32(fd);
- return header;
-}
-
-ID3v2FrameHeader *readID3v2FrameHeader(VFSFile *fd)
-{
- ID3v2FrameHeader *frameheader = g_new0(ID3v2FrameHeader,1);
- frameheader->frame_id = read_char_data(fd,4);
- frameheader->size = read_BEuint32(fd);
- frameheader->flags = read_LEuint16(fd);
- return frameheader;
-}
-
-TextInformationFrame *readTextFrame(VFSFile *fd, TextInformationFrame *frame)
-{
- frame->encoding = read_char_data(fd,1)[0];
-
- if(frame->encoding == 0)
- frame->text = read_iso8859_1(fd,frame->header.size - 1);
-
- if(frame->encoding == 1)
- frame->text = read_unicode(fd,frame->header.size - 1);
- return frame;
-}
-
-
-gchar* readFrameBody(VFSFile *fd,int size)
-{
- if(size == 0)
- return NULL;
- gchar *b = g_new0(gchar,size);
- vfs_fread(b,size,1,fd);
- return b;
-}
-
-GenericFrame *readGenericFrame(VFSFile *fd,GenericFrame *gf)
-{
- gf->header = readID3v2FrameHeader(fd);
- gf->frame_body = readFrameBody(fd,gf->header->size);
-
- return gf;
-}
-
-
-void readAllFrames(VFSFile *fd,int framesSize)
-{
- int pos = 0;
- int i = 0;
- while(pos < framesSize)
- {
- GenericFrame *gframe = g_new0(GenericFrame,1);
- gframe = readGenericFrame(fd,gframe);
- if(isValidFrame(gframe))
- {
- mowgli_dictionary_add(frames, gframe->header->frame_id, gframe);
- mowgli_node_add(gframe->header->frame_id, mowgli_node_create(), frameIDs);
- pos += gframe->header->size;
- i++;
- }else
- break;
- }
-
-}
-
-
-/* writing stuff */
-void write_int32(VFSFile *fd, guint32 val)
-{
- guint32 be_val = GUINT32_TO_BE(val);
- vfs_fwrite(&be_val,4,1,fd);
-}
-
-void write_syncsafe_int32(VFSFile *fd, guint32 val)
-{
- //TODO write the corrent function - this is just for testing
- int i = 0;
- guint32 tmp =0x0;
- guint32 mask =0x7f;
- guint32 syncVal = 0;
- tmp = val & mask;
- syncVal = tmp;
- for(i = 0;i<3;i++)
- {
- tmp = 0;
- mask <<= 7;
- tmp = val & mask;
- tmp <<=1;
- syncVal |=tmp;
- }
- guint32 be_val = GUINT32_TO_BE(syncVal);
- vfs_fwrite(&be_val,4,1,fd);
-}
-
-
-void write_ASCII(VFSFile *fd, int size, gchar* value)
-{
- vfs_fwrite(value,size,1,fd);
-}
-
-
-void write_utf8(VFSFile *fd, int size,gchar* value)
-{
- GError *error = NULL;
- gsize bytes_read = 0 , bytes_write = 0;
- gchar* isoVal = g_convert(value,size,"ISO-8859-1","UTF-8",&bytes_read,&bytes_write,&error);
- vfs_fwrite(isoVal,size,1,fd);
-}
-
-guint32 writeAllFramesToFile(VFSFile *fd)
-{
- guint32 size = 0;
- mowgli_node_t *n, *tn;
- MOWGLI_LIST_FOREACH_SAFE(n, tn, frameIDs->head)
- {
- GenericFrame *frame = (GenericFrame*)mowgli_dictionary_retrieve(frames,(gchar*)(n->data));
- if(frame)
- {
- writeGenericFrame(fd,frame);
- size += frame->header->size+10;
- }
- }
- return size;
-}
-
-void writeID3HeaderToFile(VFSFile *fd,ID3v2Header *header)
-{
- vfs_fwrite(header->id3,3,1,fd);
- vfs_fwrite(&header->version,2,1,fd);
- vfs_fwrite(&header->flags,1,1,fd);
- write_syncsafe_int32(fd,header->size);
-}
-
-void writePaddingToFile(VFSFile *fd, int ksize)
-{
- gchar padding = 0;
- int i = 0;
- for(i=0; i<ksize;i++)
- vfs_fwrite(&padding,1,1,fd);
-}
-
-
-void writeID3FrameHeaderToFile(VFSFile *fd, ID3v2FrameHeader *header)
-{
- vfs_fwrite(header->frame_id,4,1,fd);
- write_int32(fd,header->size);
- vfs_fwrite(&header->flags,2,1,fd);
-}
-
-void writeGenericFrame(VFSFile *fd,GenericFrame *frame)
-{
- writeID3FrameHeaderToFile(fd,frame->header);
- vfs_fwrite(frame->frame_body,frame->header->size,1,fd);
-}
-
-gboolean isExtendedHeader(ID3v2Header *header)
-{
- if( (header->flags & 0x40) == (0x40))
- return TRUE;
- else
- return FALSE;
-}
-
-gboolean isUnsynchronisation(ID3v2Header *header)
-{
- if((header->flags & 0x80) == 0x80)
- return TRUE;
- else
- return FALSE;
-}
-
-gboolean isExperimental(ID3v2Header *header)
-{
- if((header->flags & 0x20) == 0x20)
- return TRUE;
- else
- return FALSE;
-}
-
-
-int getFrameID(ID3v2FrameHeader *header)
-{
- int i=0;
- for(i = 0; i<ID3_TAGS_NO;i++)
- {
- if(!strcmp(header->frame_id,id3_frames[i]))
- return i;
- }
- return -1;
-}
-
-
-void skipFrame(VFSFile *fd, guint32 size)
-{
- vfs_fseek(fd,size,SEEK_CUR);
-}
-
-Tuple *assocStrInfo(Tuple *tuple, VFSFile *fd, int field,ID3v2FrameHeader header)
-{
- TextInformationFrame *frame = g_new0(TextInformationFrame,1);
- frame->header = header;
- frame = readTextFrame(fd,frame);
-/* AUDDBG("field = %s\n",frame->text);*/
- tuple_associate_string(tuple, field, NULL, frame->text);
- return tuple;
-}
-
-Tuple *assocIntInfo(Tuple *tuple, VFSFile *fd, int field,ID3v2FrameHeader header)
-{
- TextInformationFrame *frame = g_new0(TextInformationFrame,1);
- frame->header = header;
- frame = readTextFrame(fd,frame);
-/* AUDDBG("field = %s\n",frame->text);*/
- tuple_associate_int(tuple, field, NULL, atoi(frame->text));
- return tuple;
-}
-
-gboolean isValidFrame(GenericFrame *frame)
-{
- if(strlen(frame->header->frame_id) != 0)
- return TRUE;
- else
- return FALSE;
-}
-
-
-
-void add_newISO8859_1FrameFromString(const gchar *value,int id3_field)
-{
- GError *error = NULL;
- gsize bytes_read = 0 , bytes_write = 0;
- gchar* retVal = g_convert(value,strlen(value),"ISO-8859-1","UTF-8",&bytes_read,&bytes_write,&error);
- ID3v2FrameHeader *header = g_new0(ID3v2FrameHeader,1);
- header->frame_id = id3_frames[id3_field];
- header->flags = 0;
- header->size = strlen(retVal)+1;
- gchar* buf = g_new0(gchar,header->size+1);
- memcpy(buf+1,retVal,header->size);
- GenericFrame *frame = g_new0(GenericFrame,1);
- frame->header = header;
- frame->frame_body = buf;
- mowgli_dictionary_add(frames,header->frame_id,frame);
- mowgli_node_add(frame->header->frame_id, mowgli_node_create(), frameIDs);
-
-}
-
-
-void add_newFrameFromTupleStr(Tuple *tuple, int field,int id3_field)
-{
- const gchar *value = tuple_get_string(tuple,field,NULL);
- add_newISO8859_1FrameFromString(value,id3_field);
-}
-
-
-void add_newFrameFromTupleInt(Tuple *tuple,int field,int id3_field)
-{
- int intvalue = tuple_get_int(tuple,field,NULL);
- gchar *value = g_strdup_printf("%d",intvalue);
- add_newISO8859_1FrameFromString(value,id3_field);
-
-}
-
-
-
-void add_frameFromTupleStr(Tuple *tuple, int field,int id3_field)
-{
- const gchar *value = tuple_get_string(tuple,field,NULL);
- GError *error = NULL;
- gsize bytes_read = 0 , bytes_write = 0;
- gchar* retVal = g_convert(value,strlen(value),"ISO-8859-1","UTF-8",&bytes_read,&bytes_write,&error);
-
- GenericFrame *frame = mowgli_dictionary_retrieve(frames,id3_frames[id3_field]);
- if(frame != NULL)
- {
- frame->header->size = strlen(retVal)+1;
- gchar* buf = g_new0(gchar,frame->header->size+1);
- memcpy(buf+1,retVal,frame->header->size);
- frame->frame_body = buf;
- }
- else
- add_newFrameFromTupleStr(tuple,field,id3_field);
-
-}
-
-void add_frameFromTupleInt(Tuple *tuple, int field,int id3_field)
-{
- int intvalue = tuple_get_int(tuple,field,NULL);
- gchar *value = g_strdup_printf("%d",intvalue);
- GError *error = NULL;
- gsize bytes_read = 0 , bytes_write = 0;
- gchar* retVal = g_convert(value,strlen(value),"ISO-8859-1","UTF-8",&bytes_read,&bytes_write,&error);
-
- GenericFrame *frame = mowgli_dictionary_retrieve(frames,id3_frames[id3_field]);
- if(frame != NULL)
- {
- frame->header->size = strlen(retVal)+1;
- gchar* buf = g_new0(gchar,frame->header->size+1);
- memcpy(buf+1,retVal,frame->header->size);
- frame->frame_body = buf;
- }
- else
- add_newFrameFromTupleStr(tuple,field,id3_field);
-
-}
-
-gboolean id3_can_handle_file(VFSFile *f)
-{
- ID3v2Header *header = readHeader(f);
- if(!strcmp(header->id3,"ID3"))
- return TRUE;
- return FALSE;
-}
-
-
-
-Tuple *id3_populate_tuple_from_file(Tuple *tuple, VFSFile *f)
-{
- //reset file position
- vfs_fseek(f,0,SEEK_SET);
-// Tuple *tuple = tuple_new_from_filename(f->uri);
- ExtendedHeader *extHeader;
- ID3v2Header *header = readHeader(f);
- int pos = 0;
- if(isExtendedHeader(header))
- extHeader = readExtendedHeader(f);
-
- while(pos < header->size)
- {
- ID3v2FrameHeader *header = readID3v2FrameHeader(f);
- int id = getFrameID(header);
- pos = pos + header->size + 10;
- switch(id)
- {
- case ID3_ALBUM:
- {
- tuple = assocStrInfo(tuple,f,FIELD_ALBUM,*header);
- }break;
- case ID3_TITLE:
- {
- tuple = assocStrInfo(tuple,f,FIELD_TITLE,*header);
- }break;
- case ID3_COMPOSER:
- {
- // tuple = assocInfo(tuple,f,FIELD_ARTIST,*header);
- }break;
- case ID3_COPYRIGHT:
- {
- tuple = assocStrInfo(tuple,f,FIELD_COPYRIGHT,*header);
- }break;
- case ID3_DATE:
- {
- tuple = assocStrInfo(tuple,f,FIELD_DATE,*header);
- }break;
- case ID3_TIME:
- {
- // tuple = assocIntInfo(tuple,f,FIELD_LENGTH,*header);
- }break;
- case ID3_LENGTH:
- {
- tuple = assocIntInfo(tuple,f,FIELD_LENGTH,*header);
- }break;
- case ID3_ARTIST:
- {
- tuple = assocStrInfo(tuple,f,FIELD_ARTIST,*header);
- }break;
- case ID3_TRACKNR:
- {
- tuple = assocIntInfo(tuple,f,FIELD_TRACK_NUMBER,*header);
- }break;
- case ID3_YEAR:
- {
- tuple = assocIntInfo(tuple,f,FIELD_YEAR,*header);
- }break;
- case ID3_GENRE:
- {
- tuple = assocStrInfo(tuple,f,FIELD_GENRE,*header);
- }break;
- case ID3_COMMENT:
- {
- tuple = assocStrInfo(tuple,f,FIELD_COMMENT,*header);
- }break;
- default:
- {
- //we a a frame that I dont need so skip it
- skipFrame(f,header->size);
- }
- }
- }
- return tuple;
-}
-
-
-gboolean id3_write_tuple_to_file(Tuple* tuple, VFSFile *f)
-{
- VFSFile *tmp;
- vfs_fseek(f,0,SEEK_SET);
-
- ExtendedHeader *extHeader;
- if(frameIDs != NULL)
- {
- mowgli_node_t *n, *tn;
- MOWGLI_LIST_FOREACH_SAFE(n, tn, frameIDs->head)
- {
- mowgli_node_delete(n,frameIDs);
- }
- }
- frameIDs = mowgli_list_create();
- ID3v2Header *header = readHeader(f);
- int framesSize = header->size;
-
- if(isExtendedHeader(header))
- {
- extHeader = readExtendedHeader(f);
- framesSize -= 10;
- framesSize -= extHeader->padding_size;
- }
-
- //read all frames into generic frames;
- frames = mowgli_dictionary_create(strcasecmp);
- readAllFrames(f,header->size);
-
- //make the new frames from tuple and replace in the dictinonary the old frames with the new ones
- if(tuple_get_string(tuple, FIELD_ARTIST, NULL))
- add_frameFromTupleStr(tuple, FIELD_ARTIST,ID3_ARTIST);
-
-
- if(tuple_get_string(tuple, FIELD_TITLE, NULL))
- add_frameFromTupleStr(tuple, FIELD_TITLE,ID3_TITLE);
-
-
- if(tuple_get_string(tuple, FIELD_ALBUM, NULL))
- add_frameFromTupleStr(tuple, FIELD_ALBUM,ID3_ALBUM);
-
- if(tuple_get_string(tuple,FIELD_COMMENT,NULL))
- add_frameFromTupleStr(tuple,FIELD_COMMENT,ID3_COMMENT);
-
- if(tuple_get_string(tuple,FIELD_GENRE,NULL))
- add_frameFromTupleStr(tuple,FIELD_GENRE,ID3_GENRE);
-
- if(tuple_get_int(tuple,FIELD_YEAR,NULL) !=0 )
- add_frameFromTupleInt(tuple,FIELD_YEAR,ID3_YEAR);
-
- if(tuple_get_int(tuple,FIELD_TRACK_NUMBER,NULL) != 0)
- add_frameFromTupleInt(tuple,FIELD_TRACK_NUMBER,ID3_TRACKNR);
-
- const gchar *tmpdir = g_get_tmp_dir();
- gchar *tmp_path = g_strdup_printf("file://%s/%s", tmpdir, "tmp.mpc");
- tmp = vfs_fopen(tmp_path, "w+");
-
- int oldSize = header->size;
- header->size = TAG_SIZE*1024;
-
- writeID3HeaderToFile(tmp,header);
-
- int size = writeAllFramesToFile(tmp);
- writePaddingToFile(tmp,TAG_SIZE*1024-size-10);
-
- copyAudioToFile(f,tmp,oldSize);
-
-
- gchar *uri = g_strdup(f -> uri);
- vfs_fclose(tmp);
- gchar* f1 = g_filename_from_uri(tmp_path,NULL,NULL);
- gchar* f2 = g_filename_from_uri(uri,NULL,NULL);
- if (g_rename(f1,f2 ) == 0) {
- AUDDBG("the tag was updated successfully\n");
- } else {
- AUDDBG("an error has occured\n");
- }
- return TRUE;
-}
diff --git a/src/libaudtag/id3/id3.h b/src/libaudtag/id3/id3.h
deleted file mode 100644
index b8a0cca..0000000
--- a/src/libaudtag/id3/id3.h
+++ /dev/null
@@ -1,118 +0,0 @@
-#ifndef ID3_H
-
-#define ID3_H
-
-#include <libaudcore/tuple.h>
-#include <libaudcore/vfs.h>
-#include "../tag_module.h"
-
-
-typedef struct id3v2
-{
- gchar *id3;
- guint16 version;
- gchar flags;
- guint32 size;
-} ID3v2Header;
-
-typedef struct extHeader
-{
- guint32 header_size;
- guint16 flags;
- guint32 padding_size;
-}ExtendedHeader;
-
-typedef struct frameheader
-{
- gchar* frame_id;
- guint32 size;
- guint16 flags;
-}ID3v2FrameHeader;
-
-typedef struct genericframe
-{
- ID3v2FrameHeader *header;
- gchar* frame_body;
-}GenericFrame;
-
-typedef struct textframe
-{
- ID3v2FrameHeader header;
- gchar encoding;
- gchar* text;
-}TextInformationFrame;
-
-gchar *read_iso8859_1(VFSFile *fd, int size);
-
-gchar* read_unicode(VFSFile *fd, int size);
-
-guint32 read_syncsafe_int32(VFSFile *fd);
-
-ID3v2Header *readHeader(VFSFile *fd);
-
-ExtendedHeader *readExtendedHeader(VFSFile *fd);
-
-ID3v2FrameHeader *readID3v2FrameHeader(VFSFile *fd);
-
-TextInformationFrame *readTextFrame(VFSFile *fd, TextInformationFrame *frame);
-
-gchar* readFrameBody(VFSFile *fd,int size);
-
-GenericFrame *readGenericFrame(VFSFile *fd,GenericFrame *gf);
-
-void readAllFrames(VFSFile *fd,int framesSize);
-
-void write_int32(VFSFile *fd, guint32 val);
-
-void write_syncsafe_int32(VFSFile *fd, guint32 val);
-
-void write_ASCII(VFSFile *fd, int size, gchar* value);
-
-void write_utf8(VFSFile *fd, int size,gchar* value);
-
-guint32 writeAllFramesToFile(VFSFile *fd);
-
-void writeID3HeaderToFile(VFSFile *fd,ID3v2Header *header);
-
-void writePaddingToFile(VFSFile *fd, int ksize);
-
-void writeID3FrameHeaderToFile(VFSFile *fd, ID3v2FrameHeader *header);
-
-void writeGenericFrame(VFSFile *fd,GenericFrame *frame);
-
-gboolean isExtendedHeader(ID3v2Header *header);
-
-gboolean isUnsynchronisation(ID3v2Header *header);
-
-gboolean isExperimental(ID3v2Header *header);
-
-int getFrameID(ID3v2FrameHeader *header);
-
-void skipFrame(VFSFile *fd, guint32 size);
-
-Tuple *assocStrInfo(Tuple *tuple, VFSFile *fd, int field,ID3v2FrameHeader header);
-
-Tuple *assocIntInfo(Tuple *tuple, VFSFile *fd, int field,ID3v2FrameHeader header);
-
-gboolean isValidFrame(GenericFrame *frame);
-
-void add_newISO8859_1FrameFromString(const gchar *value,int id3_field);
-
-void add_newFrameFromTupleStr(Tuple *tuple, int field,int id3_field);
-
-void add_newFrameFromTupleInt(Tuple *tuple,int field,int id3_field);
-
-void add_frameFromTupleStr(Tuple *tuple, int field,int id3_field);
-
-void add_frameFromTupleInt(Tuple *tuple, int field,int id3_field);
-
-gboolean id3_can_handle_file(VFSFile *f);
-
-Tuple *id3_populate_tuple_from_file(Tuple *tuple,VFSFile *f);
-
-gboolean id3_write_tuple_to_file(Tuple* tuple, VFSFile *f);
-
-extern tag_module_t id3;
-mowgli_dictionary_t *frames ;
-mowgli_list_t *frameIDs;
-#endif
diff --git a/src/libaudtag/id3/id3v1.c b/src/libaudtag/id3/id3v1.c
new file mode 100644
index 0000000..9b593a1
--- /dev/null
+++ b/src/libaudtag/id3/id3v1.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2010 Tony Vroon
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include "id3v1.h"
+#include "../util.h"
+#include <inttypes.h>
+#include "../tag_module.h"
+
+static gboolean has_id3v1_ext;
+
+gboolean id3v1_can_handle_file(VFSFile *f)
+{
+ gchar *tag = g_new0(gchar, 4);
+
+ if (vfs_fseek(f, -355, SEEK_END))
+ return FALSE;
+ tag = read_char_data(f, 4);
+ if (!strncmp(tag, "TAG+", 4))
+ has_id3v1_ext = TRUE;
+ else
+ has_id3v1_ext = FALSE;
+
+ if (vfs_fseek(f, -128, SEEK_END))
+ return FALSE;
+ tag = read_char_data(f, 3);
+ if (!strncmp(tag, "TAG", 3))
+ {
+ g_free(tag);
+ return TRUE;
+ }
+
+ g_free(tag);
+ return FALSE;
+}
+
+static gchar *convert_to_utf8(gchar *str)
+{
+ return g_strchomp(str_to_utf8(str));
+}
+
+gboolean id3v1_read_tag (Tuple * tuple, VFSFile * f)
+{
+ gchar *title = g_new0(gchar, 30);
+ gchar *artist = g_new0(gchar, 30);
+ gchar *album = g_new0(gchar, 30);
+ gchar *year = g_new0(gchar, 4);
+ gchar *comment = g_new0(gchar, 30);
+ gchar *track = g_new0(gchar, 1);
+ gchar *genre = g_new0(gchar, 1);
+ gboolean genre_set = FALSE;
+ if (vfs_fseek(f, -125, SEEK_END))
+ return FALSE;
+ title = read_char_data(f, 30);
+ artist = read_char_data(f, 30);
+ album = read_char_data(f, 30);
+ year = read_char_data(f, 4);
+ comment = read_char_data(f, 30);
+ genre = read_char_data(f, 1);
+
+ if (comment[28] == 0 && comment[29] != 0)
+ {
+ *track = comment[29];
+ }
+
+ title = convert_to_utf8(title);
+ artist = convert_to_utf8(artist);
+ album = convert_to_utf8(album);
+ comment = convert_to_utf8(comment);
+
+ if (has_id3v1_ext)
+ {
+ vfs_fseek(f, -351, SEEK_END);
+ gchar *tmp_title = g_strconcat(title, convert_to_utf8(read_char_data(f, 60)), NULL);
+ gchar *tmp_artist = g_strconcat(artist, convert_to_utf8(read_char_data(f, 60)), NULL);
+ gchar *tmp_album = g_strconcat(album, convert_to_utf8(read_char_data(f, 60)), NULL);
+ vfs_fseek(f, -170, SEEK_END);
+ gchar *tmp_genre = g_new0(gchar, 30);
+ tmp_genre = convert_to_utf8(read_char_data(f, 30));
+ g_free(title);
+ g_free(artist);
+ g_free(album);
+ title = tmp_title;
+ artist = tmp_artist;
+ album = tmp_album;
+
+ if (g_strcmp0(tmp_genre, NULL) == 1)
+ {
+ tuple_associate_string(tuple, FIELD_GENRE, NULL, tmp_genre);
+ genre_set = TRUE;
+ }
+
+ g_free(tmp_genre);
+ }
+
+ tuple_associate_string(tuple, FIELD_TITLE, NULL, title);
+ tuple_associate_string(tuple, FIELD_ARTIST, NULL, artist);
+ tuple_associate_string(tuple, FIELD_ALBUM, NULL, album);
+ tuple_associate_int(tuple, FIELD_YEAR, NULL, atoi(year));
+ tuple_associate_string(tuple, FIELD_COMMENT, NULL, comment);
+ tuple_associate_int(tuple, FIELD_TRACK_NUMBER, NULL, *track);
+ if (!genre_set) tuple_associate_string(tuple, FIELD_GENRE, NULL, convert_numericgenre_to_text(*genre));
+
+ g_free(title);
+ g_free(artist);
+ g_free(album);
+ g_free(year);
+ g_free(comment);
+ g_free(track);
+ g_free(genre);
+
+ return TRUE;
+}
+
+gboolean id3v1_write_tag (Tuple * tuple, VFSFile * handle)
+{
+ return FALSE;
+}
+
+tag_module_t id3v1 = {
+ .name = "ID3v1",
+ .can_handle_file = id3v1_can_handle_file,
+ .read_tag = id3v1_read_tag,
+ .write_tag = id3v1_write_tag,
+};
+
diff --git a/src/libaudtag/id3/id3v1.h b/src/libaudtag/id3/id3v1.h
new file mode 100644
index 0000000..77ebee9
--- /dev/null
+++ b/src/libaudtag/id3/id3v1.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010 Tony Vroon
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+#ifndef ID3V1_H
+
+#define ID3V1_H
+
+#include <libaudcore/audstrings.h>
+#include <libaudcore/tuple.h>
+#include <libaudcore/vfs.h>
+#include "../tag_module.h"
+
+/* TAG plugin API */
+gboolean id3v1_can_handle_file(VFSFile *f);
+gboolean id3v1_read_tag (Tuple * tuple, VFSFile * handle);
+gboolean id3v1_write_tag (Tuple * tuple, VFSFile * handle);
+
+extern tag_module_t id3v1;
+#endif
diff --git a/src/libaudtag/id3/id3v22.c b/src/libaudtag/id3/id3v22.c
new file mode 100644
index 0000000..4699bf7
--- /dev/null
+++ b/src/libaudtag/id3/id3v22.c
@@ -0,0 +1,890 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ * Copyright 2010 John Lindgren
+ * Copyright 2010 Tony Vroon
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+#include <glib.h>
+
+#include <libaudcore/audstrings.h>
+
+#include "id3v22.h"
+#include "../util.h"
+
+enum
+{
+ ID3_ALBUM = 0,
+ ID3_TITLE,
+ ID3_COMPOSER,
+ ID3_COPYRIGHT,
+ ID3_DATE,
+ ID3_TIME,
+ ID3_LENGTH,
+ ID3_ARTIST,
+ ID3_TRACKNR,
+ ID3_YEAR,
+ ID3_GENRE,
+ ID3_COMMENT,
+ ID3_ENCODER,
+ ID3_TXX,
+ ID3_RVA,
+ ID3_TAGS_NO
+};
+
+static const gchar * id3_frames[ID3_TAGS_NO] = {"TAL", "TT2", "TCM", "TCR",
+"TDA", "TIM", "TLE", "TPE", "TRK", "TYE", "TCO", "COM", "TSS", "TXX", "RVA"};
+
+#pragma pack(push) /* must be byte-aligned */
+#pragma pack(1)
+typedef struct
+{
+ gchar magic[3];
+ guchar version;
+ guchar revision;
+ guchar flags;
+ guint32 size;
+}
+ID3v2Header;
+
+typedef struct
+{
+ gchar key[3];
+ guint32 size;
+}
+ID3v2FrameHeader;
+#pragma pack(pop)
+
+typedef struct
+{
+ gchar key[5];
+ guchar * data;
+ gint size;
+}
+GenericFrame;
+
+#define ID3_HEADER_SYNCSAFE 0x40
+#define ID3_HEADER_COMPRESSED 0x20
+
+#define TAG_SIZE 1
+
+static mowgli_dictionary_t * frames = NULL;
+static mowgli_list_t * frameIDs = NULL;
+
+#define write_syncsafe_int32(x) vfs_fput_be32 (syncsafe32 (x))
+
+static gboolean validate_header (ID3v2Header * header, gboolean is_footer)
+{
+ if (memcmp (header->magic, is_footer ? "3DI" : "ID3", 3))
+ return FALSE;
+
+ if ((header->version != 2) || header->revision != 0)
+ return FALSE;
+
+ header->size = unsyncsafe32 (GUINT32_FROM_BE (header->size));
+
+ AUDDBG ("Found ID3v2 %s:\n", is_footer ? "footer" : "header");
+ AUDDBG (" magic = %.3s\n", header->magic);
+ AUDDBG (" version = %d\n", (gint) header->version);
+ AUDDBG (" revision = %d\n", (gint) header->revision);
+ AUDDBG (" flags = %x\n", (gint) header->flags);
+ AUDDBG (" size = %d\n", (gint) header->size);
+ return TRUE;
+}
+
+static gboolean read_header (VFSFile * handle, gint * version, gboolean *
+ syncsafe, gsize * offset, gint * header_size, gint * data_size, gint *
+ footer_size)
+{
+ ID3v2Header header, footer;
+
+ if (vfs_fseek (handle, 0, SEEK_SET))
+ return FALSE;
+
+ if (vfs_fread (& header, 1, sizeof (ID3v2Header), handle) != sizeof
+ (ID3v2Header))
+ return FALSE;
+
+ if (validate_header (& header, FALSE))
+ {
+ * offset = 0;
+ * version = header.version;
+ * header_size = sizeof (ID3v2Header);
+ * data_size = header.size;
+ }
+ else
+ {
+ gsize end = vfs_fsize (handle);
+
+ if (end < 0)
+ return FALSE;
+
+ if (vfs_fseek (handle, end - sizeof (ID3v2Header), SEEK_SET))
+ return FALSE;
+
+ if (vfs_fread (& footer, 1, sizeof (ID3v2Header), handle) != sizeof
+ (ID3v2Header))
+ return FALSE;
+
+ if (! validate_header (& footer, TRUE))
+ return FALSE;
+
+ * offset = end - 2 * sizeof (ID3v2Header) - footer.size;
+ * version = footer.version;
+ * header_size = sizeof (ID3v2Header);
+ * data_size = footer.size;
+ * footer_size = sizeof (ID3v2Header);
+
+ if (vfs_fseek (handle, * offset, SEEK_SET))
+ return FALSE;
+
+ if (vfs_fread (& header, 1, sizeof (ID3v2Header), handle) != sizeof
+ (ID3v2Header))
+ return FALSE;
+
+ if (! validate_header (& header, FALSE))
+ return FALSE;
+ }
+
+ * syncsafe = (header.flags & ID3_HEADER_SYNCSAFE) ? TRUE : FALSE;
+
+ AUDDBG ("Offset = %d, header size = %d, data size = %d, footer size = "
+ "%d.\n", (gint) * offset, * header_size, * data_size, * footer_size);
+
+ return TRUE;
+}
+
+static gint unsyncsafe (guchar * data, gint size)
+{
+ guchar * get = data, * set = data;
+
+ while (size --)
+ {
+ guchar c = * set ++ = * get ++;
+
+ if (c == 0xff && size && ! get[0])
+ {
+ size --;
+ get ++;
+ }
+ }
+
+ return set - data;
+}
+
+static gboolean read_frame (VFSFile * handle, gint max_size, gint version,
+ gboolean syncsafe, gint * frame_size, gchar * key, guchar * * data, gint * size)
+{
+ ID3v2FrameHeader header;
+ gint skip = 0;
+
+ if ((max_size -= sizeof (ID3v2FrameHeader)) < 0)
+ return FALSE;
+
+ if (vfs_fread (& header, 1, sizeof (ID3v2FrameHeader), handle) != sizeof
+ (ID3v2FrameHeader))
+ return FALSE;
+
+ if (! header.key[0]) /* padding */
+ return FALSE;
+
+ header.size = (version == 3) ? GUINT32_FROM_BE (header.size) : unsyncsafe32
+ (GUINT32_FROM_BE (header.size));
+ header.flags = GUINT16_FROM_BE (header.flags);
+
+ if (header.size > max_size)
+ return FALSE;
+
+ AUDDBG ("Found frame:\n");
+ AUDDBG (" key = %.4s\n", header.key);
+ AUDDBG (" size = %d\n", (gint) header.size);
+ AUDDBG (" flags = %x\n", (gint) header.flags);
+
+ * frame_size = sizeof (ID3v2FrameHeader) + header.size;
+ sprintf (key, "%.4s", header.key);
+
+ if (header.flags & (ID3_FRAME_COMPRESSED | ID3_FRAME_ENCRYPTED))
+ {
+ AUDDBG ("Hit compressed/encrypted frame %s.\n", key);
+ return FALSE;
+ }
+
+ if (header.flags & ID3_FRAME_HAS_GROUP)
+ skip ++;
+ if (header.flags & ID3_FRAME_HAS_LENGTH)
+ skip += 4;
+
+ if (skip > 0 && vfs_fseek (handle, skip, SEEK_CUR))
+ return FALSE;
+
+ * size = header.size - skip;
+ * data = g_malloc (* size);
+
+ if (vfs_fread (* data, 1, * size, handle) != * size)
+ return FALSE;
+
+ if (syncsafe || (header.flags & ID3_FRAME_SYNCSAFE))
+ * size = unsyncsafe (* data, * size);
+
+ AUDDBG ("Data size = %d.\n", * size);
+ return TRUE;
+}
+
+static gchar * convert_text (const gchar * text, gint length, gint encoding,
+ gboolean nulled, gint * _converted, const gchar * * after)
+{
+ gchar * buffer = NULL;
+ gsize converted = 0;
+
+ if (nulled)
+ {
+ const guchar null16[] = {0, 0};
+ const gchar * null;
+
+ switch (encoding)
+ {
+ case 0:
+ case 3:
+ if ((null = memchr (text, 0, length)) == NULL)
+ return NULL;
+
+ length = null - text;
+
+ if (after != NULL)
+ * after = null + 1;
+
+ break;
+ case 1:
+ case 2:
+ if ((null = memfind (text, length, null16, 2)) == NULL)
+ return NULL;
+
+ length = null - text;
+
+ if (after != NULL)
+ * after = null + 2;
+
+ break;
+ }
+ }
+
+ switch (encoding)
+ {
+ case 0:
+ buffer = g_convert (text, length, "UTF-8", "ISO-8859-1", NULL,
+ & converted, NULL);
+ break;
+ case 1:
+ if (text[0] == (gchar) 0xff)
+ buffer = g_convert (text + 2, length - 2, "UTF-8", "UTF-16LE", NULL,
+ & converted, NULL);
+ else
+ buffer = g_convert (text + 2, length - 2, "UTF-8", "UTF-16BE", NULL,
+ & converted, NULL);
+
+ break;
+ case 2:
+ buffer = g_convert (text, length, "UTF-8", "UTF-16BE", NULL,
+ & converted, NULL);
+ break;
+ case 3:
+ buffer = g_malloc (length + 1);
+ memcpy (buffer, text, length);
+ buffer[length] = 0;
+ converted = length;
+ break;
+ }
+
+ if (_converted != NULL)
+ * _converted = converted;
+
+ return buffer;
+}
+
+static gchar * decode_text_frame (const guchar * data, gint size)
+{
+ return convert_text ((const gchar *) data + 1, size - 1, data[0], FALSE,
+ NULL, NULL);
+}
+
+static gboolean decode_comment_frame (const guchar * _data, gint size, gchar * *
+ lang, gchar * * type, gchar * * value)
+{
+ const gchar * data = (const gchar *) _data;
+ gchar * pair, * sep;
+ gint converted;
+
+ pair = convert_text (data + 4, size - 4, data[0], FALSE, & converted, NULL);
+
+ if (pair == NULL || (sep = memchr (pair, 0, converted)) == NULL)
+ return FALSE;
+
+ * lang = g_strndup (data + 1, 3);
+ * type = g_strdup (pair);
+ * value = g_strdup (sep + 1);
+
+ g_free (pair);
+ return TRUE;
+}
+
+static void free_generic_frame (GenericFrame * frame)
+{
+ g_free (frame->data);
+ g_free (frame);
+}
+
+static void read_all_frames (VFSFile * handle, gint version, gboolean syncsafe,
+ gint data_size)
+{
+ gint pos;
+
+ for (pos = 0; pos < data_size; )
+ {
+ gint frame_size, size;
+ gchar key[5];
+ guchar * data;
+ GenericFrame * frame;
+
+ if (! read_frame (handle, data_size - pos, version, syncsafe,
+ & frame_size, key, & data, & size))
+ break;
+
+ frame = g_malloc (sizeof (GenericFrame));
+ strcpy (frame->key, key);
+ frame->data = data;
+ frame->size = size;
+
+ mowgli_dictionary_add (frames, frame->key, frame);
+ mowgli_node_add (frame->key, mowgli_node_create (), frameIDs);
+
+ pos += frame_size;
+ }
+}
+
+static gboolean write_frame (VFSFile * handle, GenericFrame * frame, gint *
+ frame_size)
+{
+ ID3v2FrameHeader header;
+
+ memcpy (header.key, frame->key, 4);
+ header.size = syncsafe32 (frame->size);
+ header.size = GUINT32_TO_BE (header.size);
+ header.flags = 0;
+
+ if (vfs_fwrite (& header, 1, sizeof (ID3v2FrameHeader), handle) != sizeof
+ (ID3v2FrameHeader))
+ return FALSE;
+
+ if (vfs_fwrite (frame->data, 1, frame->size, handle) != frame->size)
+ return FALSE;
+
+ * frame_size = sizeof (ID3v2FrameHeader) + frame->size;
+ return TRUE;
+}
+
+static guint32 writeAllFramesToFile (VFSFile * fd)
+{
+ guint32 size = 0;
+ mowgli_node_t *n, *tn;
+ MOWGLI_LIST_FOREACH_SAFE(n, tn, frameIDs->head)
+ {
+ GenericFrame *frame = (GenericFrame *) mowgli_dictionary_retrieve(frames, (gchar *) (n->data));
+ if (frame)
+ {
+ gint frame_size;
+
+ if (! write_frame (fd, frame, & frame_size))
+ break;
+
+ size += frame_size;
+ }
+ }
+ return size;
+}
+
+static gboolean write_header (VFSFile * handle, gint size, gboolean is_footer)
+{
+ ID3v2Header header;
+
+ memcpy (header.magic, is_footer ? "3DI" : "ID3", 3);
+ header.version = 4;
+ header.revision = 0;
+ header.flags = ID3_HEADER_HAS_FOOTER;
+ header.size = syncsafe32 (size);
+ header.size = GUINT32_TO_BE (header.size);
+
+ return vfs_fwrite (& header, 1, sizeof (ID3v2Header), handle) == sizeof
+ (ID3v2Header);
+}
+
+static gint get_frame_id (const gchar * key)
+{
+ gint id;
+
+ for (id = 0; id < ID3_TAGS_NO; id ++)
+ {
+ if (! strcmp (key, id3_frames[id]))
+ return id;
+ }
+
+ return -1;
+}
+
+static void associate_string (Tuple * tuple, gint field, const gchar *
+ customfield, const guchar * data, gint size)
+{
+ gchar * text = decode_text_frame (data, size);
+
+ if (text == NULL)
+ return;
+
+ if (customfield != NULL)
+ AUDDBG ("Custom field %s = %s.\n", customfield, text);
+ else
+ AUDDBG ("Field %i = %s.\n", field, text);
+
+ tuple_associate_string (tuple, field, customfield, text);
+ g_free (text);
+}
+
+static void associate_int (Tuple * tuple, gint field, const gchar *
+ customfield, const guchar * data, gint size)
+{
+ gchar * text = decode_text_frame (data, size);
+
+ if (text == NULL)
+ return;
+
+ if (customfield != NULL)
+ AUDDBG ("Custom field %s = %s.\n", customfield, text);
+ else
+ AUDDBG ("Field %i = %s.\n", field, text);
+
+ tuple_associate_int (tuple, field, customfield, atoi (text));
+ g_free (text);
+}
+
+static void decode_comment (Tuple * tuple, const guchar * data, gint size)
+{
+ gchar * lang, * type, * value;
+
+ if (! decode_comment_frame (data, size, & lang, & type, & value))
+ return;
+
+ AUDDBG ("Comment: lang = %s, type = %s, value = %s.\n", lang, type, value);
+
+ if (! type[0]) /* blank type == actual comment */
+ tuple_associate_string (tuple, FIELD_COMMENT, NULL, value);
+
+ g_free (lang);
+ g_free (type);
+ g_free (value);
+}
+
+static void decode_txx (Tuple * tuple, const guchar * data, gint size)
+{
+ gchar * text = decode_text_frame (data, size);
+
+ if (text == NULL)
+ return;
+
+ gchar *separator = strchr(text, 0);
+
+ if (separator == NULL)
+ return;
+
+ gchar * value = separator + 1;
+ AUDDBG ("TXX: %s = %s.\n", text, value);
+ tuple_associate_string (tuple, -1, text, value);
+
+ g_free (text);
+}
+
+static gboolean decode_rva_block (const guchar * * _data, gint * _size, gint *
+ channel, gint * adjustment, gint * adjustment_unit, gint * peak, gint *
+ peak_unit)
+{
+ const guchar * data = * _data;
+ gint size = * _size;
+ gint peak_bits;
+
+ if (size < 4)
+ return FALSE;
+
+ * channel = data[0];
+ * adjustment = (gchar) data[1]; /* first byte is signed */
+ * adjustment = (* adjustment << 8) | data[2];
+ * adjustment_unit = 512;
+ peak_bits = data[3];
+
+ data += 4;
+ size -= 4;
+
+ AUDDBG ("RVA block: channel = %d, adjustment = %d/%d, peak bits = %d\n",
+ * channel, * adjustment, * adjustment_unit, peak_bits);
+
+ if (peak_bits > 0 && peak_bits < sizeof (gint) * 8)
+ {
+ gint bytes = (peak_bits + 7) / 8;
+ gint count;
+
+ if (bytes > size)
+ return FALSE;
+
+ * peak = 0;
+ * peak_unit = 1 << peak_bits;
+
+ for (count = 0; count < bytes; count ++)
+ * peak = (* peak << 8) | data[count];
+
+ data += bytes;
+ size -= count;
+
+ AUDDBG ("RVA block: peak = %d/%d\n", * peak, * peak_unit);
+ }
+ else
+ {
+ * peak = 0;
+ * peak_unit = 0;
+ }
+
+ * _data = data;
+ * _size = size;
+ return TRUE;
+}
+
+static void decode_rva (Tuple * tuple, const guchar * data, gint size)
+{
+ const gchar * domain;
+ gint channel, adjustment, adjustment_unit, peak, peak_unit;
+
+ if (memchr (data, 0, size) == NULL)
+ return;
+
+ domain = (const gchar *) data;
+
+ AUDDBG ("RVA domain: %s\n", domain);
+
+ size -= strlen (domain) + 1;
+ data += strlen (domain) + 1;
+
+ while (size > 0)
+ {
+ if (! decode_rva_block (& data, & size, & channel, & adjustment,
+ & adjustment_unit, & peak, & peak_unit))
+ break;
+
+ if (channel != 1) /* specific channel? */
+ continue;
+
+ if (tuple_get_value_type (tuple, FIELD_GAIN_GAIN_UNIT, NULL) ==
+ TUPLE_INT)
+ adjustment = adjustment * (gint64) tuple_get_int (tuple,
+ FIELD_GAIN_GAIN_UNIT, NULL) / adjustment_unit;
+ else
+ tuple_associate_int (tuple, FIELD_GAIN_GAIN_UNIT, NULL,
+ adjustment_unit);
+
+ if (peak_unit)
+ {
+ if (tuple_get_value_type (tuple, FIELD_GAIN_PEAK_UNIT, NULL) ==
+ TUPLE_INT)
+ peak = peak * (gint64) tuple_get_int (tuple,
+ FIELD_GAIN_PEAK_UNIT, NULL) / peak_unit;
+ else
+ tuple_associate_int (tuple, FIELD_GAIN_PEAK_UNIT, NULL,
+ peak_unit);
+ }
+
+ if (! strcasecmp (domain, "album"))
+ {
+ tuple_associate_int (tuple, FIELD_GAIN_ALBUM_GAIN, NULL, adjustment);
+
+ if (peak_unit)
+ tuple_associate_int (tuple, FIELD_GAIN_ALBUM_PEAK, NULL, peak);
+ }
+ else if (! strcasecmp (domain, "track"))
+ {
+ tuple_associate_int (tuple, FIELD_GAIN_TRACK_GAIN, NULL, adjustment);
+
+ if (peak_unit)
+ tuple_associate_int (tuple, FIELD_GAIN_TRACK_PEAK, NULL, peak);
+ }
+ }
+}
+
+static void decode_genre (Tuple * tuple, const guchar * data, gint size)
+{
+ gint numericgenre;
+ gchar * text = decode_text_frame (data, size);
+
+ if (text == NULL)
+ return;
+
+ if (text[0] == '(')
+ numericgenre = atoi (text + 1);
+ else
+ numericgenre = atoi (text);
+
+ if (numericgenre > 0)
+ {
+ tuple_associate_string(tuple, FIELD_GENRE, NULL, convert_numericgenre_to_text(numericgenre));
+ return;
+ }
+ tuple_associate_string(tuple, FIELD_GENRE, NULL, text);
+ g_free (text);
+ return;
+}
+
+static GenericFrame * add_generic_frame (gint id, gint size)
+{
+ GenericFrame * frame = mowgli_dictionary_retrieve (frames, id3_frames[id]);
+
+ if (frame == NULL)
+ {
+ frame = g_malloc (sizeof (GenericFrame));
+ strcpy (frame->key, id3_frames[id]);
+ mowgli_dictionary_add (frames, frame->key, frame);
+ mowgli_node_add (frame->key, mowgli_node_create (), frameIDs);
+ }
+ else
+ g_free (frame->data);
+
+ frame->data = g_malloc (size);
+ frame->size = size;
+ return frame;
+}
+
+static void add_text_frame (gint id, const gchar * text)
+{
+ gint length = strlen (text);
+ GenericFrame * frame = add_generic_frame (id, length + 1);
+
+ frame->data[0] = 3; /* UTF-8 encoding */
+ memcpy (frame->data + 1, text, length);
+}
+
+static void add_comment_frame (const gchar * text)
+{
+ gint length = strlen (text);
+ GenericFrame * frame = add_generic_frame (ID3_COMMENT, length + 5);
+
+ frame->data[0] = 3; /* UTF-8 encoding */
+ strcpy ((gchar *) frame->data + 1, "eng"); /* well, it *might* be English */
+ memcpy (frame->data + 5, text, length);
+}
+
+static void add_frameFromTupleStr (Tuple * tuple, int field, int id3_field)
+{
+ add_text_frame (id3_field, tuple_get_string (tuple, field, NULL));
+}
+
+static void add_frameFromTupleInt (Tuple * tuple, int field, int id3_field)
+{
+ gchar scratch[16];
+
+ snprintf (scratch, sizeof scratch, "%d", tuple_get_int (tuple, field, NULL));
+ add_text_frame (id3_field, scratch);
+}
+
+static gboolean id3v22_can_handle_file (VFSFile * handle)
+{
+ gint version, header_size, data_size, footer_size;
+ gboolean syncsafe;
+ gsize offset;
+
+ return read_header (handle, & version, & syncsafe, & offset, & header_size,
+ & data_size, & footer_size);
+}
+
+static gboolean id3v22_read_tag (Tuple * tuple, VFSFile * handle)
+{
+ gint version, header_size, data_size, footer_size;
+ gboolean syncsafe;
+ gsize offset;
+ gint pos;
+
+ if (! read_header (handle, & version, & syncsafe, & offset, & header_size,
+ & data_size, & footer_size))
+ return FALSE;
+
+ for (pos = 0; pos < data_size; )
+ {
+ gint frame_size, size, id;
+ gchar key[5];
+ guchar * data;
+
+ if (! read_frame (handle, data_size - pos, version, syncsafe,
+ & frame_size, key, & data, & size))
+ break;
+
+ id = get_frame_id (key);
+
+ switch (id)
+ {
+ case ID3_ALBUM:
+ associate_string (tuple, FIELD_ALBUM, NULL, data, size);
+ break;
+ case ID3_TITLE:
+ associate_string (tuple, FIELD_TITLE, NULL, data, size);
+ break;
+ case ID3_COMPOSER:
+ associate_string (tuple, FIELD_COMPOSER, NULL, data, size);
+ break;
+ case ID3_COPYRIGHT:
+ associate_string (tuple, FIELD_COPYRIGHT, NULL, data, size);
+ break;
+ case ID3_DATE:
+ associate_string (tuple, FIELD_DATE, NULL, data, size);
+ break;
+ case ID3_TIME:
+ associate_int (tuple, FIELD_LENGTH, NULL, data, size);
+ break;
+ case ID3_LENGTH:
+ associate_int (tuple, FIELD_LENGTH, NULL, data, size);
+ break;
+ case ID3_ARTIST:
+ associate_string (tuple, FIELD_ARTIST, NULL, data, size);
+ break;
+ case ID3_TRACKNR:
+ associate_int (tuple, FIELD_TRACK_NUMBER, NULL, data, size);
+ break;
+ case ID3_YEAR:
+ associate_int (tuple, FIELD_YEAR, NULL, data, size);
+ break;
+ case ID3_GENRE:
+ decode_genre (tuple, data, size);
+ break;
+ case ID3_COMMENT:
+ decode_comment (tuple, data, size);
+ break;
+ case ID3_ENCODER:
+ associate_string (tuple, -1, "encoder", data, size);
+ break;
+ case ID3_TXX:
+ decode_txx (tuple, data, size);
+ break;
+ case ID3_RVA:
+ decode_rva (tuple, data, size);
+ break;
+ default:
+ AUDDBG ("Ignoring unsupported ID3 frame %s.\n", key);
+ break;
+ }
+
+ g_free (data);
+ pos += frame_size;
+ }
+
+ return TRUE;
+}
+
+static gboolean parse_pic (const guchar * data, gint size, gchar * * mime,
+ gint * type, gchar * * desc, void * * image_data, gint * image_size)
+{
+ const guchar * sep;
+ const guchar * after;
+
+ if (size < 2 || (sep = memchr (data + 1, 0, size - 2)) == NULL)
+ return FALSE;
+
+ if ((* desc = convert_text ((const gchar *) sep + 2, data + size - sep - 2,
+ data[0], TRUE, NULL, (const gchar * *) & after)) == NULL)
+ return FALSE;
+
+ * mime = g_strdup ((const gchar *) data + 1);
+ * type = sep[1];
+ * image_data = g_memdup (after, data + size - after);
+ * image_size = data + size - after;
+
+ AUDDBG ("PIC: mime = %s, type = %d, desc = %s, size = %d.\n", * mime,
+ * type, * desc, * image_size);
+ return TRUE;
+}
+
+static gboolean id3v22_read_image (VFSFile * handle, void * * image_data, gint *
+ image_size)
+{
+ gint version, header_size, data_size, footer_size, parsed;
+ gboolean syncsafe;
+ gsize offset;
+ gboolean found = FALSE;
+
+ if (! read_header (handle, & version, & syncsafe, & offset, & header_size,
+ & data_size, & footer_size))
+ return FALSE;
+
+ for (parsed = 0; parsed < data_size && ! found; )
+ {
+ gint frame_size, size, type;
+ gchar key[5];
+ guchar * data;
+ gchar * mime, * desc;
+
+ if (! read_frame (handle, data_size - parsed, version, syncsafe,
+ & frame_size, key, & data, & size))
+ break;
+
+ if (! strcmp (key, "PIC") && parse_pic (data, size, & mime, & type,
+ & desc, image_data, image_size))
+ {
+ g_free (mime);
+ g_free (desc);
+
+ if (type == 3) /* album cover */
+ found = TRUE;
+ else if (type == 0) /* iTunes */
+ found = TRUE;
+ else if (*image_data != NULL)
+ {
+ g_free(*image_data);
+ *image_data = NULL;
+ }
+ }
+
+ g_free (data);
+ parsed += frame_size;
+ }
+
+ return found;
+}
+
+static void free_frame_cb (mowgli_dictionary_elem_t * element, void * unused)
+{
+ free_generic_frame (element->data);
+}
+
+static void free_frame_dictionary (void)
+{
+ mowgli_dictionary_destroy (frames, free_frame_cb, NULL);
+ frames = NULL;
+}
+
+static gboolean id3v22_write_tag (Tuple * tuple, VFSFile * f)
+{
+ return FALSE;
+}
+
+tag_module_t id3v24 =
+{
+ .name = "ID3v2.2",
+ .can_handle_file = id3v22_can_handle_file,
+ .read_tag = id3v22_read_tag,
+ .read_image = id3v22_read_image,
+ .write_tag = id3v22_write_tag,
+};
diff --git a/src/libaudtag/id3/id3v22.h b/src/libaudtag/id3/id3v22.h
new file mode 100644
index 0000000..2801d21
--- /dev/null
+++ b/src/libaudtag/id3/id3v22.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 Tony Vroon
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 2 or version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+#ifndef AUDTAG_ID3V22_H
+#define AUDTAG_ID3V22_H
+
+#include "../audtag.h"
+#include "../tag_module.h"
+#include "../util.h"
+
+extern tag_module_t id3v22;
+
+#endif
diff --git a/src/libaudtag/id3/id3v24.c b/src/libaudtag/id3/id3v24.c
new file mode 100644
index 0000000..499048d
--- /dev/null
+++ b/src/libaudtag/id3/id3v24.c
@@ -0,0 +1,1106 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ * Copyright 2010 John Lindgren
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+#include <glib.h>
+
+#include <libaudcore/audstrings.h>
+
+#include "id3v24.h"
+#include "../util.h"
+
+enum
+{
+ ID3_ALBUM = 0,
+ ID3_TITLE,
+ ID3_COMPOSER,
+ ID3_COPYRIGHT,
+ ID3_DATE,
+ ID3_TIME,
+ ID3_LENGTH,
+ ID3_ARTIST,
+ ID3_TRACKNR,
+ ID3_YEAR,
+ ID3_GENRE,
+ ID3_COMMENT,
+ ID3_PRIVATE,
+ ID3_ENCODER,
+ ID3_RECORDING_TIME,
+ ID3_TXXX,
+ ID3_RVA2,
+ ID3_TAGS_NO
+};
+
+static const gchar * id3_frames[ID3_TAGS_NO] = {"TALB","TIT2","TCOM", "TCOP",
+ "TDAT", "TIME", "TLEN", "TPE1", "TRCK", "TYER","TCON", "COMM", "PRIV", "TSSE",
+ "TDRC", "TXXX", "RVA2"};
+
+static const guchar PRIMARY_CLASS_MUSIC[16] = {0xBC, 0x7D, 0x60, 0xD1, 0x23,
+ 0xE3, 0xE2, 0x4B, 0x86, 0xA1, 0x48, 0xA4, 0x2A, 0x28, 0x44, 0x1E};
+static const guchar PRIMARY_CLASS_AUDIO[16] = {0x29, 0x0F, 0xCD, 0x01, 0x4E,
+ 0xDA, 0x57, 0x41, 0x89, 0x7B, 0x62, 0x75, 0xD5, 0x0C, 0x4F, 0x11};
+static const guchar SECONDARY_CLASS_AUDIOBOOK[16] = {0xEB, 0x6B, 0x23, 0xE0,
+ 0x81, 0xC2, 0xDE, 0x4E, 0xA3, 0x6D, 0x7A, 0xF7, 0x6A, 0x3D, 0x45, 0xB5};
+static const guchar SECONDARY_CLASS_SPOKENWORD[16] = {0x13, 0x2A, 0x17, 0x3A,
+ 0xD9, 0x2B, 0x31, 0x48, 0x83, 0x5B, 0x11, 0x4F, 0x6A, 0x95, 0x94, 0x3F};
+static const guchar SECONDARY_CLASS_NEWS[16] = {0x9B, 0xDB, 0x77, 0x66, 0xA0,
+ 0xE5, 0x63, 0x40, 0xA1, 0xAD, 0xAC, 0xEB, 0x52, 0x84, 0x0C, 0xF1};
+static const guchar SECONDARY_CLASS_TALKSHOW[16] = {0x67, 0x4A, 0x82, 0x1B,
+ 0x80, 0x3F, 0x3E, 0x4E, 0x9C, 0xDE, 0xF7, 0x36, 0x1B, 0x0F, 0x5F, 0x1B};
+static const guchar SECONDARY_CLASS_GAMES_CLIP[16] = {0x68, 0x33, 0x03, 0x00,
+ 0x09, 0x50, 0xC3, 0x4A, 0xA8, 0x20, 0x5D, 0x2D, 0x09, 0xA4, 0xE7, 0xC1};
+static const guchar SECONDARY_CLASS_GAMES_SONG[16] = {0x31, 0xF7, 0x4F, 0xF2,
+ 0xFC, 0x96, 0x0F, 0x4D, 0xA2, 0xF5, 0x5A, 0x34, 0x83, 0x68, 0x2B, 0x1A};
+
+#pragma pack(push) /* must be byte-aligned */
+#pragma pack(1)
+typedef struct
+{
+ gchar magic[3];
+ guchar version;
+ guchar revision;
+ guchar flags;
+ guint32 size;
+}
+ID3v2Header;
+
+typedef struct
+{
+ gchar key[4];
+ guint32 size;
+ guint16 flags;
+}
+ID3v2FrameHeader;
+#pragma pack(pop)
+
+typedef struct
+{
+ gchar key[5];
+ guchar * data;
+ gint size;
+}
+GenericFrame;
+
+#define ID3_HEADER_SYNCSAFE 0x80
+#define ID3_HEADER_HAS_EXTENDED_HEADER 0x40
+#define ID3_HEADER_HAS_FOOTER 0x10
+
+#define ID3_FRAME_HAS_GROUP 0x0040
+#define ID3_FRAME_COMPRESSED 0x0008
+#define ID3_FRAME_ENCRYPTED 0x0004
+#define ID3_FRAME_SYNCSAFE 0x0002
+#define ID3_FRAME_HAS_LENGTH 0x0001
+
+#define TAG_SIZE 1
+
+static mowgli_dictionary_t * frames = NULL;
+static mowgli_list_t * frameIDs = NULL;
+
+#define write_syncsafe_int32(x) vfs_fput_be32 (syncsafe32 (x))
+
+static gboolean skip_extended_header_3 (VFSFile * handle, gint * _size)
+{
+ guint32 size;
+
+ if (vfs_fread (& size, 1, 4, handle) != 4)
+ return FALSE;
+
+ size = GUINT32_FROM_BE (size);
+
+ AUDDBG ("Found v2.3 extended header, size = %d.\n", (gint) size);
+
+ if (vfs_fseek (handle, size, SEEK_CUR))
+ return FALSE;
+
+ * _size = 4 + size;
+ return TRUE;
+}
+
+static gboolean skip_extended_header_4 (VFSFile * handle, gint * _size)
+{
+ guint32 size;
+
+ if (vfs_fread (& size, 1, 4, handle) != 4)
+ return FALSE;
+
+ size = unsyncsafe32 (GUINT32_FROM_BE (size));
+
+ AUDDBG ("Found v2.4 extended header, size = %d.\n", (gint) size);
+
+ if (vfs_fseek (handle, size - 4, SEEK_CUR))
+ return FALSE;
+
+ * _size = size;
+ return TRUE;
+}
+
+static gboolean validate_header (ID3v2Header * header, gboolean is_footer)
+{
+ if (memcmp (header->magic, is_footer ? "3DI" : "ID3", 3))
+ return FALSE;
+
+ if ((header->version != 3 && header->version != 4) || header->revision != 0)
+ return FALSE;
+
+ header->size = unsyncsafe32 (GUINT32_FROM_BE (header->size));
+
+ AUDDBG ("Found ID3v2 %s:\n", is_footer ? "footer" : "header");
+ AUDDBG (" magic = %.3s\n", header->magic);
+ AUDDBG (" version = %d\n", (gint) header->version);
+ AUDDBG (" revision = %d\n", (gint) header->revision);
+ AUDDBG (" flags = %x\n", (gint) header->flags);
+ AUDDBG (" size = %d\n", (gint) header->size);
+ return TRUE;
+}
+
+static gboolean read_header (VFSFile * handle, gint * version, gboolean *
+ syncsafe, gsize * offset, gint * header_size, gint * data_size, gint *
+ footer_size)
+{
+ ID3v2Header header, footer;
+
+ if (vfs_fseek (handle, 0, SEEK_SET))
+ return FALSE;
+
+ if (vfs_fread (& header, 1, sizeof (ID3v2Header), handle) != sizeof
+ (ID3v2Header))
+ return FALSE;
+
+ if (validate_header (& header, FALSE))
+ {
+ * offset = 0;
+ * version = header.version;
+ * header_size = sizeof (ID3v2Header);
+ * data_size = header.size;
+
+ if (header.flags & ID3_HEADER_HAS_FOOTER)
+ {
+ if (vfs_fseek (handle, header.size, SEEK_CUR))
+ return FALSE;
+
+ if (vfs_fread (& footer, 1, sizeof (ID3v2Header), handle) != sizeof
+ (ID3v2Header))
+ return FALSE;
+
+ if (! validate_header (& footer, TRUE))
+ return FALSE;
+
+ * footer_size = sizeof (ID3v2Header);
+ }
+ else
+ * footer_size = 0;
+ }
+ else
+ {
+ gsize end = vfs_fsize (handle);
+
+ if (end < 0)
+ return FALSE;
+
+ if (vfs_fseek (handle, end - sizeof (ID3v2Header), SEEK_SET))
+ return FALSE;
+
+ if (vfs_fread (& footer, 1, sizeof (ID3v2Header), handle) != sizeof
+ (ID3v2Header))
+ return FALSE;
+
+ if (! validate_header (& footer, TRUE))
+ return FALSE;
+
+ * offset = end - 2 * sizeof (ID3v2Header) - footer.size;
+ * version = footer.version;
+ * header_size = sizeof (ID3v2Header);
+ * data_size = footer.size;
+ * footer_size = sizeof (ID3v2Header);
+
+ if (vfs_fseek (handle, * offset, SEEK_SET))
+ return FALSE;
+
+ if (vfs_fread (& header, 1, sizeof (ID3v2Header), handle) != sizeof
+ (ID3v2Header))
+ return FALSE;
+
+ if (! validate_header (& header, FALSE))
+ return FALSE;
+ }
+
+ * syncsafe = (header.flags & ID3_HEADER_SYNCSAFE) ? TRUE : FALSE;
+
+ if (header.flags & ID3_HEADER_HAS_EXTENDED_HEADER)
+ {
+ gint extended_size = 0;
+
+ if (header.version == 3)
+ {
+ if (! skip_extended_header_3 (handle, & extended_size))
+ return FALSE;
+ }
+ else if (header.version == 4)
+ {
+ if (! skip_extended_header_4 (handle, & extended_size))
+ return FALSE;
+ }
+
+ * header_size += extended_size;
+ * data_size -= extended_size;
+ }
+
+ AUDDBG ("Offset = %d, header size = %d, data size = %d, footer size = "
+ "%d.\n", (gint) * offset, * header_size, * data_size, * footer_size);
+
+ return TRUE;
+}
+
+static gint unsyncsafe (guchar * data, gint size)
+{
+ guchar * get = data, * set = data;
+
+ while (size --)
+ {
+ guchar c = * set ++ = * get ++;
+
+ if (c == 0xff && size && ! get[0])
+ {
+ size --;
+ get ++;
+ }
+ }
+
+ return set - data;
+}
+
+static gboolean read_frame (VFSFile * handle, gint max_size, gint version,
+ gboolean syncsafe, gint * frame_size, gchar * key, guchar * * data, gint * size)
+{
+ ID3v2FrameHeader header;
+ gint skip = 0;
+
+ if ((max_size -= sizeof (ID3v2FrameHeader)) < 0)
+ return FALSE;
+
+ if (vfs_fread (& header, 1, sizeof (ID3v2FrameHeader), handle) != sizeof
+ (ID3v2FrameHeader))
+ return FALSE;
+
+ if (! header.key[0]) /* padding */
+ return FALSE;
+
+ header.size = (version == 3) ? GUINT32_FROM_BE (header.size) : unsyncsafe32
+ (GUINT32_FROM_BE (header.size));
+ header.flags = GUINT16_FROM_BE (header.flags);
+
+ if (header.size > max_size)
+ return FALSE;
+
+ AUDDBG ("Found frame:\n");
+ AUDDBG (" key = %.4s\n", header.key);
+ AUDDBG (" size = %d\n", (gint) header.size);
+ AUDDBG (" flags = %x\n", (gint) header.flags);
+
+ * frame_size = sizeof (ID3v2FrameHeader) + header.size;
+ sprintf (key, "%.4s", header.key);
+
+ if (header.flags & (ID3_FRAME_COMPRESSED | ID3_FRAME_ENCRYPTED))
+ {
+ AUDDBG ("Hit compressed/encrypted frame %s.\n", key);
+ return FALSE;
+ }
+
+ if (header.flags & ID3_FRAME_HAS_GROUP)
+ skip ++;
+ if (header.flags & ID3_FRAME_HAS_LENGTH)
+ skip += 4;
+
+ if (skip > 0 && vfs_fseek (handle, skip, SEEK_CUR))
+ return FALSE;
+
+ * size = header.size - skip;
+ * data = g_malloc (* size);
+
+ if (vfs_fread (* data, 1, * size, handle) != * size)
+ return FALSE;
+
+ if (syncsafe || (header.flags & ID3_FRAME_SYNCSAFE))
+ * size = unsyncsafe (* data, * size);
+
+ AUDDBG ("Data size = %d.\n", * size);
+ return TRUE;
+}
+
+static gchar * convert_text (const gchar * text, gint length, gint encoding,
+ gboolean nulled, gint * _converted, const gchar * * after)
+{
+ gchar * buffer = NULL;
+ gsize converted = 0;
+
+ if (nulled)
+ {
+ const guchar null16[] = {0, 0};
+ const gchar * null;
+
+ switch (encoding)
+ {
+ case 0:
+ case 3:
+ if ((null = memchr (text, 0, length)) == NULL)
+ return NULL;
+
+ length = null - text;
+
+ if (after != NULL)
+ * after = null + 1;
+
+ break;
+ case 1:
+ case 2:
+ if ((null = memfind (text, length, null16, 2)) == NULL)
+ return NULL;
+
+ length = null - text;
+
+ if (after != NULL)
+ * after = null + 2;
+
+ break;
+ }
+ }
+
+ switch (encoding)
+ {
+ case 0:
+ buffer = g_convert (text, length, "UTF-8", "ISO-8859-1", NULL,
+ & converted, NULL);
+ break;
+ case 1:
+ if (text[0] == (gchar) 0xff)
+ buffer = g_convert (text + 2, length - 2, "UTF-8", "UTF-16LE", NULL,
+ & converted, NULL);
+ else
+ buffer = g_convert (text + 2, length - 2, "UTF-8", "UTF-16BE", NULL,
+ & converted, NULL);
+
+ break;
+ case 2:
+ buffer = g_convert (text, length, "UTF-8", "UTF-16BE", NULL,
+ & converted, NULL);
+ break;
+ case 3:
+ buffer = g_malloc (length + 1);
+ memcpy (buffer, text, length);
+ buffer[length] = 0;
+ converted = length;
+ break;
+ }
+
+ if (_converted != NULL)
+ * _converted = converted;
+
+ return buffer;
+}
+
+static gchar * decode_text_frame (const guchar * data, gint size)
+{
+ return convert_text ((const gchar *) data + 1, size - 1, data[0], FALSE,
+ NULL, NULL);
+}
+
+static gboolean decode_comment_frame (const guchar * _data, gint size, gchar * *
+ lang, gchar * * type, gchar * * value)
+{
+ const gchar * data = (const gchar *) _data;
+ gchar * pair, * sep;
+ gint converted;
+
+ pair = convert_text (data + 4, size - 4, data[0], FALSE, & converted, NULL);
+
+ if (pair == NULL || (sep = memchr (pair, 0, converted)) == NULL)
+ return FALSE;
+
+ * lang = g_strndup (data + 1, 3);
+ * type = g_strdup (pair);
+ * value = g_strdup (sep + 1);
+
+ g_free (pair);
+ return TRUE;
+}
+
+static void free_generic_frame (GenericFrame * frame)
+{
+ g_free (frame->data);
+ g_free (frame);
+}
+
+static void read_all_frames (VFSFile * handle, gint version, gboolean syncsafe,
+ gint data_size)
+{
+ gint pos;
+
+ for (pos = 0; pos < data_size; )
+ {
+ gint frame_size, size;
+ gchar key[5];
+ guchar * data;
+ GenericFrame * frame;
+
+ if (! read_frame (handle, data_size - pos, version, syncsafe,
+ & frame_size, key, & data, & size))
+ break;
+
+ frame = g_malloc (sizeof (GenericFrame));
+ strcpy (frame->key, key);
+ frame->data = data;
+ frame->size = size;
+
+ mowgli_dictionary_add (frames, frame->key, frame);
+ mowgli_node_add (frame->key, mowgli_node_create (), frameIDs);
+
+ pos += frame_size;
+ }
+}
+
+static gboolean write_frame (VFSFile * handle, GenericFrame * frame, gint *
+ frame_size)
+{
+ ID3v2FrameHeader header;
+
+ memcpy (header.key, frame->key, 4);
+ header.size = syncsafe32 (frame->size);
+ header.size = GUINT32_TO_BE (header.size);
+ header.flags = 0;
+
+ if (vfs_fwrite (& header, 1, sizeof (ID3v2FrameHeader), handle) != sizeof
+ (ID3v2FrameHeader))
+ return FALSE;
+
+ if (vfs_fwrite (frame->data, 1, frame->size, handle) != frame->size)
+ return FALSE;
+
+ * frame_size = sizeof (ID3v2FrameHeader) + frame->size;
+ return TRUE;
+}
+
+static guint32 writeAllFramesToFile (VFSFile * fd)
+{
+ guint32 size = 0;
+ mowgli_node_t *n, *tn;
+ MOWGLI_LIST_FOREACH_SAFE(n, tn, frameIDs->head)
+ {
+ GenericFrame *frame = (GenericFrame *) mowgli_dictionary_retrieve(frames, (gchar *) (n->data));
+ if (frame)
+ {
+ gint frame_size;
+
+ if (! write_frame (fd, frame, & frame_size))
+ break;
+
+ size += frame_size;
+ }
+ }
+ return size;
+}
+
+static gboolean write_header (VFSFile * handle, gint size, gboolean is_footer)
+{
+ ID3v2Header header;
+
+ memcpy (header.magic, is_footer ? "3DI" : "ID3", 3);
+ header.version = 4;
+ header.revision = 0;
+ header.flags = ID3_HEADER_HAS_FOOTER;
+ header.size = syncsafe32 (size);
+ header.size = GUINT32_TO_BE (header.size);
+
+ return vfs_fwrite (& header, 1, sizeof (ID3v2Header), handle) == sizeof
+ (ID3v2Header);
+}
+
+static gint get_frame_id (const gchar * key)
+{
+ gint id;
+
+ for (id = 0; id < ID3_TAGS_NO; id ++)
+ {
+ if (! strcmp (key, id3_frames[id]))
+ return id;
+ }
+
+ return -1;
+}
+
+static void associate_string (Tuple * tuple, gint field, const gchar *
+ customfield, const guchar * data, gint size)
+{
+ gchar * text = decode_text_frame (data, size);
+
+ if (text == NULL)
+ return;
+
+ if (customfield != NULL)
+ AUDDBG ("Custom field %s = %s.\n", customfield, text);
+ else
+ AUDDBG ("Field %i = %s.\n", field, text);
+
+ tuple_associate_string (tuple, field, customfield, text);
+ g_free (text);
+}
+
+static void associate_int (Tuple * tuple, gint field, const gchar *
+ customfield, const guchar * data, gint size)
+{
+ gchar * text = decode_text_frame (data, size);
+
+ if (text == NULL)
+ return;
+
+ if (customfield != NULL)
+ AUDDBG ("Custom field %s = %s.\n", customfield, text);
+ else
+ AUDDBG ("Field %i = %s.\n", field, text);
+
+ tuple_associate_int (tuple, field, customfield, atoi (text));
+ g_free (text);
+}
+
+static void decode_private_info (Tuple * tuple, const guchar * data, gint size)
+{
+ gchar * text = g_strndup ((const gchar *) data, size);
+
+ if (!strncmp(text, "WM/", 3))
+ {
+ gchar *separator = strchr(text, 0);
+ if (separator == NULL)
+ goto DONE;
+
+ gchar * value = separator + 1;
+ if (!strncmp(text, "WM/MediaClassPrimaryID", 22))
+ {
+ if (!memcmp(value, PRIMARY_CLASS_MUSIC, 16))
+ tuple_associate_string (tuple, -1, "media-class", "Music");
+ if (!memcmp(value, PRIMARY_CLASS_AUDIO, 16))
+ tuple_associate_string (tuple, -1, "media-class", "Audio (non-music)");
+ } else if (!strncmp(text, "WM/MediaClassSecondaryID", 24))
+ {
+ if (!memcmp(value, SECONDARY_CLASS_AUDIOBOOK, 16))
+ tuple_associate_string (tuple, -1, "media-class", "Audio Book");
+ if (!memcmp(value, SECONDARY_CLASS_SPOKENWORD, 16))
+ tuple_associate_string (tuple, -1, "media-class", "Spoken Word");
+ if (!memcmp(value, SECONDARY_CLASS_NEWS, 16))
+ tuple_associate_string (tuple, -1, "media-class", "News");
+ if (!memcmp(value, SECONDARY_CLASS_TALKSHOW, 16))
+ tuple_associate_string (tuple, -1, "media-class", "Talk Show");
+ if (!memcmp(value, SECONDARY_CLASS_GAMES_CLIP, 16))
+ tuple_associate_string (tuple, -1, "media-class", "Game Audio (clip)");
+ if (!memcmp(value, SECONDARY_CLASS_GAMES_SONG, 16))
+ tuple_associate_string (tuple, -1, "media-class", "Game Soundtrack");
+ } else {
+ AUDDBG("Unrecognised tag %s (Windows Media) ignored\n", text);
+ }
+ } else {
+ AUDDBG("Unable to decode private data, skipping: %s\n", text);
+ }
+
+DONE:
+ g_free (text);
+}
+
+static void decode_comment (Tuple * tuple, const guchar * data, gint size)
+{
+ gchar * lang, * type, * value;
+
+ if (! decode_comment_frame (data, size, & lang, & type, & value))
+ return;
+
+ AUDDBG ("Comment: lang = %s, type = %s, value = %s.\n", lang, type, value);
+
+ if (! type[0]) /* blank type == actual comment */
+ tuple_associate_string (tuple, FIELD_COMMENT, NULL, value);
+
+ g_free (lang);
+ g_free (type);
+ g_free (value);
+}
+
+static void decode_txxx (Tuple * tuple, const guchar * data, gint size)
+{
+ gchar * text = decode_text_frame (data, size);
+
+ if (text == NULL)
+ return;
+
+ gchar *separator = strchr(text, 0);
+
+ if (separator == NULL)
+ return;
+
+ gchar * value = separator + 1;
+ AUDDBG ("TXXX: %s = %s.\n", text, value);
+ tuple_associate_string (tuple, -1, text, value);
+
+ g_free (text);
+}
+
+static gboolean decode_rva2_block (const guchar * * _data, gint * _size, gint *
+ channel, gint * adjustment, gint * adjustment_unit, gint * peak, gint *
+ peak_unit)
+{
+ const guchar * data = * _data;
+ gint size = * _size;
+ gint peak_bits;
+
+ if (size < 4)
+ return FALSE;
+
+ * channel = data[0];
+ * adjustment = (gchar) data[1]; /* first byte is signed */
+ * adjustment = (* adjustment << 8) | data[2];
+ * adjustment_unit = 512;
+ peak_bits = data[3];
+
+ data += 4;
+ size -= 4;
+
+ AUDDBG ("RVA2 block: channel = %d, adjustment = %d/%d, peak bits = %d\n",
+ * channel, * adjustment, * adjustment_unit, peak_bits);
+
+ if (peak_bits > 0 && peak_bits < sizeof (gint) * 8)
+ {
+ gint bytes = (peak_bits + 7) / 8;
+ gint count;
+
+ if (bytes > size)
+ return FALSE;
+
+ * peak = 0;
+ * peak_unit = 1 << peak_bits;
+
+ for (count = 0; count < bytes; count ++)
+ * peak = (* peak << 8) | data[count];
+
+ data += bytes;
+ size -= count;
+
+ AUDDBG ("RVA2 block: peak = %d/%d\n", * peak, * peak_unit);
+ }
+ else
+ {
+ * peak = 0;
+ * peak_unit = 0;
+ }
+
+ * _data = data;
+ * _size = size;
+ return TRUE;
+}
+
+static void decode_rva2 (Tuple * tuple, const guchar * data, gint size)
+{
+ const gchar * domain;
+ gint channel, adjustment, adjustment_unit, peak, peak_unit;
+
+ if (memchr (data, 0, size) == NULL)
+ return;
+
+ domain = (const gchar *) data;
+
+ AUDDBG ("RVA2 domain: %s\n", domain);
+
+ size -= strlen (domain) + 1;
+ data += strlen (domain) + 1;
+
+ while (size > 0)
+ {
+ if (! decode_rva2_block (& data, & size, & channel, & adjustment,
+ & adjustment_unit, & peak, & peak_unit))
+ break;
+
+ if (channel != 1) /* specific channel? */
+ continue;
+
+ if (tuple_get_value_type (tuple, FIELD_GAIN_GAIN_UNIT, NULL) ==
+ TUPLE_INT)
+ adjustment = adjustment * (gint64) tuple_get_int (tuple,
+ FIELD_GAIN_GAIN_UNIT, NULL) / adjustment_unit;
+ else
+ tuple_associate_int (tuple, FIELD_GAIN_GAIN_UNIT, NULL,
+ adjustment_unit);
+
+ if (peak_unit)
+ {
+ if (tuple_get_value_type (tuple, FIELD_GAIN_PEAK_UNIT, NULL) ==
+ TUPLE_INT)
+ peak = peak * (gint64) tuple_get_int (tuple,
+ FIELD_GAIN_PEAK_UNIT, NULL) / peak_unit;
+ else
+ tuple_associate_int (tuple, FIELD_GAIN_PEAK_UNIT, NULL,
+ peak_unit);
+ }
+
+ if (! strcasecmp (domain, "album"))
+ {
+ tuple_associate_int (tuple, FIELD_GAIN_ALBUM_GAIN, NULL, adjustment);
+
+ if (peak_unit)
+ tuple_associate_int (tuple, FIELD_GAIN_ALBUM_PEAK, NULL, peak);
+ }
+ else if (! strcasecmp (domain, "track"))
+ {
+ tuple_associate_int (tuple, FIELD_GAIN_TRACK_GAIN, NULL, adjustment);
+
+ if (peak_unit)
+ tuple_associate_int (tuple, FIELD_GAIN_TRACK_PEAK, NULL, peak);
+ }
+ }
+}
+
+static void decode_genre (Tuple * tuple, const guchar * data, gint size)
+{
+ gint numericgenre;
+ gchar * text = decode_text_frame (data, size);
+
+ if (text == NULL)
+ return;
+
+ if (text[0] == '(')
+ numericgenre = atoi (text + 1);
+ else
+ numericgenre = atoi (text);
+
+ if (numericgenre > 0)
+ {
+ tuple_associate_string(tuple, FIELD_GENRE, NULL, convert_numericgenre_to_text(numericgenre));
+ return;
+ }
+ tuple_associate_string(tuple, FIELD_GENRE, NULL, text);
+ g_free (text);
+ return;
+}
+
+static GenericFrame * add_generic_frame (gint id, gint size)
+{
+ GenericFrame * frame = mowgli_dictionary_retrieve (frames, id3_frames[id]);
+
+ if (frame == NULL)
+ {
+ frame = g_malloc (sizeof (GenericFrame));
+ strcpy (frame->key, id3_frames[id]);
+ mowgli_dictionary_add (frames, frame->key, frame);
+ mowgli_node_add (frame->key, mowgli_node_create (), frameIDs);
+ }
+ else
+ g_free (frame->data);
+
+ frame->data = g_malloc (size);
+ frame->size = size;
+ return frame;
+}
+
+static void add_text_frame (gint id, const gchar * text)
+{
+ gint length = strlen (text);
+ GenericFrame * frame = add_generic_frame (id, length + 1);
+
+ frame->data[0] = 3; /* UTF-8 encoding */
+ memcpy (frame->data + 1, text, length);
+}
+
+static void add_comment_frame (const gchar * text)
+{
+ gint length = strlen (text);
+ GenericFrame * frame = add_generic_frame (ID3_COMMENT, length + 5);
+
+ frame->data[0] = 3; /* UTF-8 encoding */
+ strcpy ((gchar *) frame->data + 1, "eng"); /* well, it *might* be English */
+ memcpy (frame->data + 5, text, length);
+}
+
+static void add_frameFromTupleStr (Tuple * tuple, int field, int id3_field)
+{
+ add_text_frame (id3_field, tuple_get_string (tuple, field, NULL));
+}
+
+static void add_frameFromTupleInt (Tuple * tuple, int field, int id3_field)
+{
+ gchar scratch[16];
+
+ snprintf (scratch, sizeof scratch, "%d", tuple_get_int (tuple, field, NULL));
+ add_text_frame (id3_field, scratch);
+}
+
+static gboolean id3v24_can_handle_file (VFSFile * handle)
+{
+ gint version, header_size, data_size, footer_size;
+ gboolean syncsafe;
+ gsize offset;
+
+ return read_header (handle, & version, & syncsafe, & offset, & header_size,
+ & data_size, & footer_size);
+}
+
+static gboolean id3v24_read_tag (Tuple * tuple, VFSFile * handle)
+{
+ gint version, header_size, data_size, footer_size;
+ gboolean syncsafe;
+ gsize offset;
+ gint pos;
+
+ if (! read_header (handle, & version, & syncsafe, & offset, & header_size,
+ & data_size, & footer_size))
+ return FALSE;
+
+ for (pos = 0; pos < data_size; )
+ {
+ gint frame_size, size, id;
+ gchar key[5];
+ guchar * data;
+
+ if (! read_frame (handle, data_size - pos, version, syncsafe,
+ & frame_size, key, & data, & size))
+ break;
+
+ id = get_frame_id (key);
+
+ switch (id)
+ {
+ case ID3_ALBUM:
+ associate_string (tuple, FIELD_ALBUM, NULL, data, size);
+ break;
+ case ID3_TITLE:
+ associate_string (tuple, FIELD_TITLE, NULL, data, size);
+ break;
+ case ID3_COMPOSER:
+ associate_string (tuple, FIELD_COMPOSER, NULL, data, size);
+ break;
+ case ID3_COPYRIGHT:
+ associate_string (tuple, FIELD_COPYRIGHT, NULL, data, size);
+ break;
+ case ID3_DATE:
+ associate_string (tuple, FIELD_DATE, NULL, data, size);
+ break;
+ case ID3_TIME:
+ associate_int (tuple, FIELD_LENGTH, NULL, data, size);
+ break;
+ case ID3_LENGTH:
+ associate_int (tuple, FIELD_LENGTH, NULL, data, size);
+ break;
+ case ID3_ARTIST:
+ associate_string (tuple, FIELD_ARTIST, NULL, data, size);
+ break;
+ case ID3_TRACKNR:
+ associate_int (tuple, FIELD_TRACK_NUMBER, NULL, data, size);
+ break;
+ case ID3_YEAR:
+ case ID3_RECORDING_TIME:
+ associate_int (tuple, FIELD_YEAR, NULL, data, size);
+ break;
+ case ID3_GENRE:
+ decode_genre (tuple, data, size);
+ break;
+ case ID3_COMMENT:
+ decode_comment (tuple, data, size);
+ break;
+ case ID3_PRIVATE:
+ decode_private_info (tuple, data, size);
+ break;
+ case ID3_ENCODER:
+ associate_string (tuple, -1, "encoder", data, size);
+ break;
+ case ID3_TXXX:
+ decode_txxx (tuple, data, size);
+ break;
+ case ID3_RVA2:
+ decode_rva2 (tuple, data, size);
+ break;
+ default:
+ AUDDBG ("Ignoring unsupported ID3 frame %s.\n", key);
+ break;
+ }
+
+ g_free (data);
+ pos += frame_size;
+ }
+
+ return TRUE;
+}
+
+static gboolean parse_apic (const guchar * data, gint size, gchar * * mime,
+ gint * type, gchar * * desc, void * * image_data, gint * image_size)
+{
+ const guchar * sep;
+ const guchar * after;
+
+ if (size < 2 || (sep = memchr (data + 1, 0, size - 2)) == NULL)
+ return FALSE;
+
+ if ((* desc = convert_text ((const gchar *) sep + 2, data + size - sep - 2,
+ data[0], TRUE, NULL, (const gchar * *) & after)) == NULL)
+ return FALSE;
+
+ * mime = g_strdup ((const gchar *) data + 1);
+ * type = sep[1];
+ * image_data = g_memdup (after, data + size - after);
+ * image_size = data + size - after;
+
+ AUDDBG ("APIC: mime = %s, type = %d, desc = %s, size = %d.\n", * mime,
+ * type, * desc, * image_size);
+ return TRUE;
+}
+
+static gboolean id3v24_read_image (VFSFile * handle, void * * image_data, gint *
+ image_size)
+{
+ gint version, header_size, data_size, footer_size, parsed;
+ gboolean syncsafe;
+ gsize offset;
+ gboolean found = FALSE;
+
+ if (! read_header (handle, & version, & syncsafe, & offset, & header_size,
+ & data_size, & footer_size))
+ return FALSE;
+
+ for (parsed = 0; parsed < data_size && ! found; )
+ {
+ gint frame_size, size, type;
+ gchar key[5];
+ guchar * data;
+ gchar * mime, * desc;
+
+ if (! read_frame (handle, data_size - parsed, version, syncsafe,
+ & frame_size, key, & data, & size))
+ break;
+
+ if (! strcmp (key, "APIC") && parse_apic (data, size, & mime, & type,
+ & desc, image_data, image_size))
+ {
+ g_free (mime);
+ g_free (desc);
+
+ if (type == 3) /* album cover */
+ found = TRUE;
+ else if (type == 0) /* iTunes */
+ found = TRUE;
+ else if (*image_data != NULL)
+ {
+ g_free(*image_data);
+ *image_data = NULL;
+ }
+ }
+
+ g_free (data);
+ parsed += frame_size;
+ }
+
+ return found;
+}
+
+static void free_frame_cb (mowgli_dictionary_elem_t * element, void * unused)
+{
+ free_generic_frame (element->data);
+}
+
+static void free_frame_dictionary (void)
+{
+ mowgli_dictionary_destroy (frames, free_frame_cb, NULL);
+ frames = NULL;
+}
+
+static gboolean id3v24_write_tag (Tuple * tuple, VFSFile * f)
+{
+ gint version, header_size, data_size, footer_size;
+ gboolean syncsafe;
+ gsize offset;
+
+ if (! read_header (f, & version, & syncsafe, & offset, & header_size,
+ & data_size, & footer_size))
+ return FALSE;
+
+ if (frameIDs != NULL)
+ {
+ mowgli_node_t *n, *tn;
+ MOWGLI_LIST_FOREACH_SAFE(n, tn, frameIDs->head)
+ {
+ mowgli_node_delete(n, frameIDs);
+ }
+ }
+ frameIDs = mowgli_list_create();
+
+ //read all frames into generic frames;
+ frames = mowgli_dictionary_create(strcasecmp);
+ read_all_frames (f, version, syncsafe, data_size);
+
+ //make the new frames from tuple and replace in the dictionary the old frames with the new ones
+ if (tuple_get_string(tuple, FIELD_ARTIST, NULL))
+ add_frameFromTupleStr(tuple, FIELD_ARTIST, ID3_ARTIST);
+
+ if (tuple_get_string(tuple, FIELD_TITLE, NULL))
+ add_frameFromTupleStr(tuple, FIELD_TITLE, ID3_TITLE);
+
+ if (tuple_get_string(tuple, FIELD_ALBUM, NULL))
+ add_frameFromTupleStr(tuple, FIELD_ALBUM, ID3_ALBUM);
+
+ if (tuple_get_string (tuple, FIELD_COMMENT, NULL) != NULL)
+ add_comment_frame (tuple_get_string (tuple, FIELD_COMMENT, NULL));
+
+ if (tuple_get_string(tuple, FIELD_GENRE, NULL))
+ add_frameFromTupleStr(tuple, FIELD_GENRE, ID3_GENRE);
+
+ if (tuple_get_int(tuple, FIELD_YEAR, NULL) != 0)
+ add_frameFromTupleInt(tuple, FIELD_YEAR, ID3_YEAR);
+
+ if (tuple_get_int(tuple, FIELD_TRACK_NUMBER, NULL) != 0)
+ add_frameFromTupleInt(tuple, FIELD_TRACK_NUMBER, ID3_TRACKNR);
+
+ if (! offset)
+ {
+ if (! cut_beginning_tag (f, header_size + data_size + footer_size))
+ return FALSE;
+ }
+ else
+ {
+ if (offset + header_size + data_size + footer_size != vfs_fsize (f))
+ return FALSE;
+
+ if (vfs_ftruncate (f, offset))
+ return FALSE;
+ }
+
+ offset = vfs_fsize (f);
+
+ if (offset < 0 || vfs_fseek (f, offset, SEEK_SET) || ! write_header (f, 0,
+ FALSE))
+ return FALSE;
+
+ data_size = writeAllFramesToFile (f);
+ free_frame_dictionary ();
+
+ if (! write_header (f, data_size, TRUE) || vfs_fseek (f, offset, SEEK_SET)
+ || ! write_header (f, data_size, FALSE))
+ return FALSE;
+
+ return TRUE;
+}
+
+tag_module_t id3v24 =
+{
+ .name = "ID3v2.3/4",
+ .can_handle_file = id3v24_can_handle_file,
+ .read_tag = id3v24_read_tag,
+ .read_image = id3v24_read_image,
+ .write_tag = id3v24_write_tag,
+};
diff --git a/src/libaudtag/id3/id3v24.h b/src/libaudtag/id3/id3v24.h
new file mode 100644
index 0000000..1fdb3db
--- /dev/null
+++ b/src/libaudtag/id3/id3v24.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 John Lindgren
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 2 or version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
+#ifndef AUDTAG_ID3V2_H
+#define AUDTAG_ID3V2_H
+
+#include "../audtag.h"
+#include "../tag_module.h"
+#include "../util.h"
+
+extern tag_module_t id3v24;
+
+#endif
diff --git a/src/libaudtag/tag_module.c b/src/libaudtag/tag_module.c
index e1b110f..e8c8b3f 100644
--- a/src/libaudtag/tag_module.c
+++ b/src/libaudtag/tag_module.c
@@ -1,30 +1,66 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
#include <glib.h>
#include <libaudcore/tuple.h>
#include <libaudcore/vfs.h>
+
+#include "audtag.h"
#include "util.h"
#include "tag_module.h"
#include "wma/module.h"
-#include "id3/id3.h"
+#include "id3/id3v1.h"
+#include "id3/id3v24.h"
#include "ape/ape.h"
-#include "aac/aac.h"
+/* #include "aac/aac.h" */
void init_tag_modules(void)
{
- mowgli_node_add(&wma, mowgli_node_create(), &tag_modules);
- mowgli_node_add(&id3, mowgli_node_create(), &tag_modules);
- mowgli_node_add(&ape, mowgli_node_create(), &tag_modules);
- mowgli_node_add(&aac, mowgli_node_create(), &tag_modules);
+ mowgli_node_add((void *)&id3v24, &id3v24.node, &tag_modules);
+ mowgli_node_add((void *)&ape, &ape.node, &tag_modules);
+ mowgli_node_add((void *)&id3v1, &id3v1.node, &tag_modules);
}
-tag_module_t *find_tag_module(VFSFile * fd)
+tag_module_t * find_tag_module (VFSFile * fd, gint new_type)
{
- mowgli_node_t *mod, *tmod;
- MOWGLI_LIST_FOREACH_SAFE(mod, tmod, tag_modules.head)
- {
- vfs_fseek(fd,0,SEEK_SET);
- if (((tag_module_t*)(mod->data))->can_handle_file(fd))
- return (tag_module_t*)(mod->data);
- }
+ mowgli_node_t *mod, *tmod;
+ MOWGLI_LIST_FOREACH_SAFE(mod, tmod, tag_modules.head)
+ {
+ if (vfs_fseek(fd, 0, SEEK_SET))
+ {
+ AUDDBG("not a seekable file\n");
+ return NULL;
+ }
+ if (((tag_module_t *) (mod->data))->can_handle_file(fd))
+ return (tag_module_t *) (mod->data);
+ }
+
+ /* No existing tag; see if we can create a new one. */
+ if (new_type != TAG_TYPE_NONE)
+ {
+ MOWGLI_LIST_FOREACH_SAFE (mod, tmod, tag_modules.head)
+ {
+ if (((tag_module_t *) (mod->data))->type == new_type)
+ return mod->data;
+ }
+ }
AUDDBG("no module found\n");
return NULL;
diff --git a/src/libaudtag/tag_module.h b/src/libaudtag/tag_module.h
index f25af42..2edfd9c 100644
--- a/src/libaudtag/tag_module.h
+++ b/src/libaudtag/tag_module.h
@@ -1,3 +1,23 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
/* Interface of the tagging library */
#ifndef TAG_MODULE_H
@@ -9,21 +29,26 @@ G_BEGIN_DECLS
#include <mowgli.h>
#include "libaudcore/tuple.h"
#include "libaudcore/vfs.h"
-
+
mowgli_list_t tag_modules;
int number_of_modules;
typedef Tuple* pTuple;
typedef struct _module {
+ gchar *name;
+ gint type; /* set to TAG_TYPE_NONE if the module cannot create new tags */
gboolean(*can_handle_file) (VFSFile *fd);
- pTuple(*populate_tuple_from_file)(Tuple *tuple, VFSFile* fd);
- gboolean(*write_tuple_to_file) (Tuple * tuple, VFSFile *fd);
+ gboolean (* read_tag) (Tuple * tuple, VFSFile * handle);
+ gboolean (* read_image) (VFSFile * handle, void * * data, gint * size);
+ gboolean (* write_tag) (Tuple * tuple, VFSFile * handle);
+
+ mowgli_node_t node;
} tag_module_t;
/* this function must be modified when including new modules */
void init_tag_modules(void);
-tag_module_t *find_tag_module(VFSFile *fd);
+tag_module_t * find_tag_module (VFSFile * handle, gint new_type);
G_END_DECLS
#endif /* TAG_MODULE_H */
diff --git a/src/libaudtag/util.c b/src/libaudtag/util.c
index c7e06be..d1c0bea 100644
--- a/src/libaudtag/util.c
+++ b/src/libaudtag/util.c
@@ -1,3 +1,23 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
#include <glib.h>
#include "util.h"
#include <inttypes.h>
@@ -11,17 +31,14 @@ time_t unix_time(guint64 win_time)
guint16 get_year(guint64 win_time)
{
- GDate* d = g_date_new();
+ GDate *d = g_date_new();
g_date_set_time_t(d, unix_time(win_time));
guint16 year = g_date_get_year(d);
g_date_free(d);
return year;
}
-Tuple *makeTuple(Tuple *tuple, const gchar* title, const gchar* artist,
- const gchar* comment, const gchar* album,
- const gchar * genre, const gchar* year,
- const gchar* filePath, int tracnr)
+Tuple *makeTuple(Tuple * tuple, const gchar * title, const gchar * artist, const gchar * comment, const gchar * album, const gchar * genre, const gchar * year, const gchar * filePath, int tracnr)
{
tuple_associate_string(tuple, FIELD_ARTIST, NULL, artist);
@@ -35,11 +52,11 @@ Tuple *makeTuple(Tuple *tuple, const gchar* title, const gchar* artist,
return tuple;
}
-const gchar* get_complete_filepath(Tuple *tuple)
+const gchar *get_complete_filepath(Tuple * tuple)
{
- const gchar* filepath;
- const gchar* dir;
- const gchar* file;
+ const gchar *filepath;
+ const gchar *dir;
+ const gchar *file;
dir = tuple_get_string(tuple, FIELD_FILE_PATH, NULL);
file = tuple_get_string(tuple, FIELD_FILE_NAME, NULL);
@@ -48,31 +65,31 @@ const gchar* get_complete_filepath(Tuple *tuple)
return filepath;
}
-void print_tuple(Tuple *tuple)
+void print_tuple(Tuple * tuple)
{
#if WMA_DEBUG
AUDDBG("--------------TUPLE PRINT --------------------\n");
- const gchar* title = tuple_get_string(tuple, FIELD_TITLE, NULL);
+ const gchar *title = tuple_get_string(tuple, FIELD_TITLE, NULL);
AUDDBG("title = %s\n", title);
/* artist */
- const gchar* artist = tuple_get_string(tuple, FIELD_ARTIST, NULL);
+ const gchar *artist = tuple_get_string(tuple, FIELD_ARTIST, NULL);
AUDDBG("artist = %s\n", artist);
/* copyright */
- const gchar* copyright = tuple_get_string(tuple, FIELD_COPYRIGHT, NULL);
+ const gchar *copyright = tuple_get_string(tuple, FIELD_COPYRIGHT, NULL);
AUDDBG("copyright = %s\n", copyright);
/* comment / description */
- const gchar* comment = tuple_get_string(tuple, FIELD_COMMENT, NULL);
+ const gchar *comment = tuple_get_string(tuple, FIELD_COMMENT, NULL);
AUDDBG("comment = %s\n", comment);
/* codec name */
- const gchar* codec_name = tuple_get_string(tuple, FIELD_CODEC, NULL);
+ const gchar *codec_name = tuple_get_string(tuple, FIELD_CODEC, NULL);
AUDDBG("codec = %s\n", codec_name);
/* album */
- const gchar* album = tuple_get_string(tuple, FIELD_ALBUM, NULL);
+ const gchar *album = tuple_get_string(tuple, FIELD_ALBUM, NULL);
AUDDBG("Album = %s\n", album);
/*track number */
@@ -80,7 +97,7 @@ void print_tuple(Tuple *tuple)
AUDDBG("Track nr = %d\n", track_nr);
/* genre */
- const gchar* genre = tuple_get_string(tuple, FIELD_GENRE, NULL);
+ const gchar *genre = tuple_get_string(tuple, FIELD_GENRE, NULL);
AUDDBG("Genre = %s \n", genre);
/* length */
@@ -92,50 +109,40 @@ void print_tuple(Tuple *tuple)
AUDDBG("Year = %d\n", year);
/* quality */
- const gchar* quality = tuple_get_string(tuple, FIELD_QUALITY, NULL);
+ const gchar *quality = tuple_get_string(tuple, FIELD_QUALITY, NULL);
AUDDBG("quality = %s\n", quality);
/* path */
- const gchar* path = tuple_get_string(tuple, FIELD_FILE_PATH, NULL);
+ const gchar *path = tuple_get_string(tuple, FIELD_FILE_PATH, NULL);
AUDDBG("path = %s\n", path);
/* filename */
- const gchar* filename = tuple_get_string(tuple, FIELD_FILE_NAME, NULL);
+ const gchar *filename = tuple_get_string(tuple, FIELD_FILE_NAME, NULL);
AUDDBG("filename = %s\n", filename);
AUDDBG("-----------------END---------------------\n");
#endif
}
-void seek(VFSFile *f, long pos)
-{
-
- vfs_fseek(f, pos, SEEK_SET);
-}
-
-void skip(VFSFile *f, int amount)
+gchar *read_char_data(VFSFile * fd, int size)
{
- vfs_fseek(f, amount, SEEK_CUR);
-}
-
-gchar *read_char_data(VFSFile *fd, int size)
-{
- gchar *value = g_new0(gchar, size);
+ gchar *value = g_new0(gchar, size + 1);
vfs_fread(value, size, 1, fd);
return value;
}
-gboolean write_char_data(VFSFile *f, gchar *data, size_t i)
+gboolean write_char_data(VFSFile * f, gchar * data, size_t i)
{
- return (vfs_fwrite(data, i, 1, f) == i);
+ return (vfs_fwrite(data, i, 1, f) == i);
}
-gchar* utf8(gunichar2* s)
+
+gchar *utf8(gunichar2 * s)
{
g_return_val_if_fail(s != NULL, NULL);
return g_utf16_to_utf8(s, -1, NULL, NULL, NULL);
}
-gunichar2 *fread_utf16(VFSFile* f, guint64 size)
+gunichar2 *fread_utf16(VFSFile * f, guint64 size)
{
gunichar2 *p = (gunichar2 *) g_malloc0(size);
if (vfs_fread(p, 1, size, f) != size)
@@ -143,18 +150,18 @@ gunichar2 *fread_utf16(VFSFile* f, guint64 size)
g_free(p);
p = NULL;
}
- gchar * s = utf8(p);
+ gchar *s = utf8(p);
AUDDBG("Converted to UTF8: '%s'\n", s);
g_free(s);
return p;
}
-gboolean write_utf16(VFSFile *f, gunichar2 *data, size_t i)
+gboolean write_utf16(VFSFile * f, gunichar2 * data, size_t i)
{
- return (vfs_fwrite(data, i, 1, f) == i);
+ return (vfs_fwrite(data, i, 1, f) == i);
}
-guint8 read_uint8(VFSFile *fd)
+guint8 read_uint8(VFSFile * fd)
{
guint16 i;
if (vfs_fread(&i, 1, 1, fd) == 1)
@@ -164,102 +171,90 @@ guint8 read_uint8(VFSFile *fd)
return -1;
}
-guint16 read_LEuint16(VFSFile *fd)
+guint16 read_LEuint16(VFSFile * fd)
{
guint16 a;
if (vfs_fget_le16(&a, fd))
- {
- AUDDBG("read_LEuint16 %d\n", a);
return a;
- } else
+ else
return -1;
}
-guint16 read_BEuint16(VFSFile *fd)
+guint16 read_BEuint16(VFSFile * fd)
{
guint16 a;
if (vfs_fget_be16(&a, fd))
- {
- AUDDBG("read_BEuint16 %d\n", a);
return a;
- } else
+ else
return -1;
}
-guint32 read_LEuint32(VFSFile *fd)
+guint32 read_LEuint32(VFSFile * fd)
{
guint32 a;
if (vfs_fget_le32(&a, fd))
- {
- AUDDBG("read_LEuint32 %d\n", a);
return a;
- } else
+ else
return -1;
}
-guint32 read_BEuint32(VFSFile *fd)
+guint32 read_BEuint32(VFSFile * fd)
{
guint32 a;
if (vfs_fget_be32(&a, fd))
- {
- AUDDBG("read_BEuint32 %d\n", a);
return a;
- } else
+ else
return -1;
}
-guint64 read_LEuint64(VFSFile *fd)
+guint64 read_LEuint64(VFSFile * fd)
{
guint64 a;
if (vfs_fget_le64(&a, fd))
- {
- AUDDBG("read_LEuint64 %"PRId64"\n", a);
return a;
- } else
+ else
return -1;
}
-guint64 read_BEuint64(VFSFile *fd)
+guint64 read_BEuint64(VFSFile * fd)
{
guint64 a;
if (vfs_fget_be64(&a, fd))
- {
- AUDDBG("read_BEuint14 %"PRId64"\n", a);
return a;
- } else
+ else
return 1;
}
-gboolean write_uint8(VFSFile *fd, guint8 val)
+gboolean write_uint8(VFSFile * fd, guint8 val)
{
return (vfs_fwrite(&val, 1, 1, fd) == 1);
}
-gboolean write_LEuint16(VFSFile *fd, guint16 val)
+gboolean write_LEuint16(VFSFile * fd, guint16 val)
{
guint16 le_val = GUINT32_TO_LE(val);
return (vfs_fwrite(&le_val, 2, 1, fd) == 2);
}
-gboolean write_BEuint32(VFSFile *fd, guint32 val)
+gboolean write_BEuint32(VFSFile * fd, guint32 val)
{
guint32 be_val = GUINT32_TO_BE(val);
return (vfs_fwrite(&be_val, 4, 1, fd) == 4);
}
-gboolean write_LEuint32(VFSFile *fd, guint32 val)
+gboolean write_LEuint32(VFSFile * fd, guint32 val)
{
guint32 le_val = GUINT32_TO_LE(val);
return (vfs_fwrite(&le_val, 4, 1, fd) == 4);
}
-gboolean write_LEuint64(VFSFile *fd, guint64 val)
+gboolean write_LEuint64(VFSFile * fd, guint64 val)
{
guint64 le_val = GUINT64_TO_LE(val);
return (vfs_fwrite(&le_val, 8, 1, fd) == 8);
}
-void copyAudioToFile(VFSFile *from, VFSFile *to, guint32 pos)
+void copyAudioToFile(VFSFile * from, VFSFile * to, guint32 pos)
{
vfs_fseek(from, pos, SEEK_SET);
while (vfs_feof(from) == 0)
@@ -270,7 +265,7 @@ void copyAudioToFile(VFSFile *from, VFSFile *to, guint32 pos)
}
}
-void copyAudioData(VFSFile* from, VFSFile *to, guint32 pos_from, guint32 pos_to)
+void copyAudioData(VFSFile * from, VFSFile * to, guint32 pos_from, guint32 pos_to)
{
vfs_fseek(from, pos_from, SEEK_SET);
int bytes_read = pos_from;
@@ -289,3 +284,193 @@ void copyAudioData(VFSFile* from, VFSFile *to, guint32 pos_from, guint32 pos_to)
vfs_fwrite(buf2, nn, 1, to);
}
}
+
+gboolean cut_beginning_tag (VFSFile * handle, gsize tag_size)
+{
+ guchar buffer[16384];
+ gsize offset = 0, readed;
+
+ if (! tag_size)
+ return TRUE;
+
+ do
+ {
+ if (vfs_fseek (handle, offset + tag_size, SEEK_SET))
+ return FALSE;
+
+ readed = vfs_fread (buffer, 1, sizeof buffer, handle);
+
+ if (vfs_fseek (handle, offset, SEEK_SET))
+ return FALSE;
+
+ if (vfs_fwrite (buffer, 1, readed, handle) != readed)
+ return FALSE;
+
+ offset += readed;
+ }
+ while (readed);
+
+ return vfs_ftruncate (handle, offset) == 0;
+}
+
+gchar *convert_numericgenre_to_text(gint numericgenre)
+{
+ const struct
+ {
+ gint numericgenre;
+ gchar *genre;
+ }
+ table[] =
+ {
+ {GENRE_BLUES, "Blues"},
+ {GENRE_CLASSIC_ROCK, "Classic Rock"},
+ {GENRE_COUNTRY, "Country"},
+ {GENRE_DANCE, "Dance"},
+ {GENRE_DISCO, "Disco"},
+ {GENRE_FUNK, "Funk"},
+ {GENRE_GRUNGE, "Grunge"},
+ {GENRE_HIPHOP, "Hip-Hop"},
+ {GENRE_JAZZ, "Jazz"},
+ {GENRE_METAL, "Metal"},
+ {GENRE_NEW_AGE, "New Age"},
+ {GENRE_OLDIES, "Oldies"},
+ {GENRE_OTHER, "Other"},
+ {GENRE_POP, "Pop"},
+ {GENRE_R_B, "R&B"},
+ {GENRE_RAP, "Rap"},
+ {GENRE_REGGAE, "Reggae"},
+ {GENRE_ROCK, "Rock"},
+ {GENRE_TECHNO, "Techno"},
+ {GENRE_INDUSTRIAL, "Industrial"},
+ {GENRE_ALTERNATIVE, "Alternative"},
+ {GENRE_SKA, "Ska"},
+ {GENRE_DEATH_METAL, "Death Metal"},
+ {GENRE_PRANKS, "Pranks"},
+ {GENRE_SOUNDTRACK, "Soundtrack"},
+ {GENRE_EURO_TECHNO, "Euro-Techno"},
+ {GENRE_AMBIENT, "Ambient"},
+ {GENRE_TRIP_HOP, "Trip-Hop"},
+ {GENRE_VOCAL, "Vocal"},
+ {GENRE_JAZZ_FUNK, "Jazz+Funk"},
+ {GENRE_FUSION, "Fusion"},
+ {GENRE_TRANCE, "Trance"},
+ {GENRE_CLASSICAL, "Classical"},
+ {GENRE_INSTRUMENTAL, "Instrumental"},
+ {GENRE_ACID, "Acid"},
+ {GENRE_HOUSE, "House"},
+ {GENRE_GAME, "Game"},
+ {GENRE_SOUND_CLIP, "Sound Clip"},
+ {GENRE_GOSPEL, "Gospel"},
+ {GENRE_NOISE, "Noise"},
+ {GENRE_ALTERNROCK, "AlternRock"},
+ {GENRE_BASS, "Bass"},
+ {GENRE_SOUL, "Soul"},
+ {GENRE_PUNK, "Punk"},
+ {GENRE_SPACE, "Space"},
+ {GENRE_MEDITATIVE, "Meditative"},
+ {GENRE_INSTRUMENTAL_POP, "Instrumental Pop"},
+ {GENRE_INSTRUMENTAL_ROCK, "Instrumental Rock"},
+ {GENRE_ETHNIC, "Ethnic"},
+ {GENRE_GOTHIC, "Gothic"},
+ {GENRE_DARKWAVE, "Darkwave"},
+ {GENRE_TECHNO_INDUSTRIAL, "Techno-Industrial"},
+ {GENRE_ELECTRONIC, "Electronic"},
+ {GENRE_POP_FOLK, "Pop-Folk"},
+ {GENRE_EURODANCE, "Eurodance"},
+ {GENRE_DREAM, "Dream"},
+ {GENRE_SOUTHERN_ROCK, "Southern Rock"},
+ {GENRE_COMEDY, "Comedy"},
+ {GENRE_CULT, "Cult"},
+ {GENRE_GANGSTA, "Gangsta"},
+ {GENRE_TOP40, "Top 40"},
+ {GENRE_CHRISTIAN_RAP, "Christian Rap"},
+ {GENRE_POP_FUNK, "Pop/Funk"},
+ {GENRE_JUNGLE, "Jungle"},
+ {GENRE_NATIVE_AMERICAN, "Native American"},
+ {GENRE_CABARET, "Cabaret"},
+ {GENRE_NEW_WAVE, "New Wave"},
+ {GENRE_PSYCHADELIC, "Psychadelic"},
+ {GENRE_RAVE, "Rave"},
+ {GENRE_SHOWTUNES, "Showtunes"},
+ {GENRE_TRAILER, "Trailer"},
+ {GENRE_LO_FI, "Lo-Fi"},
+ {GENRE_TRIBAL, "Tribal"},
+ {GENRE_ACID_PUNK, "Acid Punk"},
+ {GENRE_ACID_JAZZ, "Acid Jazz"},
+ {GENRE_POLKA, "Polka"},
+ {GENRE_RETRO, "Retro"},
+ {GENRE_MUSICAL, "Musical"},
+ {GENRE_ROCK_ROLL, "Rock & Roll"},
+ {GENRE_HARD_ROCK, "Hard Rock"},
+ {GENRE_FOLK, "Folk"},
+ {GENRE_FOLK_ROCK, "Folk-Rock"},
+ {GENRE_NATIONAL_FOLK, "National Folk"},
+ {GENRE_SWING, "Swing"},
+ {GENRE_FAST_FUSION, "Fast Fusion"},
+ {GENRE_BEBOB, "Bebob"},
+ {GENRE_LATIN, "Latin"},
+ {GENRE_REVIVAL, "Revival"},
+ {GENRE_CELTIC, "Celtic"},
+ {GENRE_BLUEGRASS, "Bluegrass"},
+ {GENRE_AVANTGARDE, "Avantgarde"},
+ {GENRE_GOTHIC_ROCK, "Gothic Rock"},
+ {GENRE_PROGRESSIVE_ROCK, "Progressive Rock"},
+ {GENRE_PSYCHEDELIC_ROCK, "Psychedelic Rock"},
+ {GENRE_SYMPHONIC_ROCK, "Symphonic Rock"},
+ {GENRE_SLOW_ROCK, "Slow Rock"},
+ {GENRE_BIG_BAND, "Big Band"},
+ {GENRE_CHORUS, "Chorus"},
+ {GENRE_EASY_LISTENING, "Easy Listening"},
+ {GENRE_ACOUSTIC, "Acoustic"},
+ {GENRE_HUMOUR, "Humour"},
+ {GENRE_SPEECH, "Speech"},
+ {GENRE_CHANSON, "Chanson"},
+ {GENRE_OPERA, "Opera"},
+ {GENRE_CHAMBER_MUSIC, "Chamber Music"},
+ {GENRE_SONATA, "Sonata"},
+ {GENRE_SYMPHONY, "Symphony"},
+ {GENRE_BOOTY_BASS, "Booty Bass"},
+ {GENRE_PRIMUS, "Primus"},
+ {GENRE_PORN_GROOVE, "Porn Groove"},
+ {GENRE_SATIRE, "Satire"},
+ {GENRE_SLOW_JAM, "Slow Jam"},
+ {GENRE_CLUB, "Club"},
+ {GENRE_TANGO, "Tango"},
+ {GENRE_SAMBA, "Samba"},
+ {GENRE_FOLKLORE, "Folklore"},
+ {GENRE_BALLAD, "Ballad"},
+ {GENRE_POWER_BALLAD, "Power Ballad"},
+ {GENRE_RHYTHMIC_SOUL, "Rhythmic Soul"},
+ {GENRE_FREESTYLE, "Freestyle"},
+ {GENRE_DUET, "Duet"},
+ {GENRE_PUNK_ROCK, "Punk Rock"},
+ {GENRE_DRUM_SOLO, "Drum Solo"},
+ {GENRE_A_CAPELLA, "A capella"},
+ {GENRE_EURO_HOUSE, "Euro-House"},
+ };
+
+ gint count;
+
+ for (count = 0; count < G_N_ELEMENTS(table); count++)
+ {
+ if (table[count].numericgenre == numericgenre)
+ {
+ return table[count].genre;
+ }
+ }
+
+ return "Unknown";
+}
+
+guint32 unsyncsafe32 (guint32 x)
+{
+ return (x & 0x7f) | ((x & 0x7f00) >> 1) | ((x & 0x7f0000) >> 2) | ((x &
+ 0x7f000000) >> 3);
+}
+
+guint32 syncsafe32 (guint32 x)
+{
+ return (x & 0x7f) | ((x & 0x3f80) << 1) | ((x & 0x1fc000) << 2) | ((x &
+ 0xfe00000) << 3);
+}
+
diff --git a/src/libaudtag/util.h b/src/libaudtag/util.h
index 5b6918a..0e6a4f3 100644
--- a/src/libaudtag/util.h
+++ b/src/libaudtag/util.h
@@ -1,3 +1,23 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
#ifndef TAGUTIL_H
#define TAGUTIL_H
@@ -6,10 +26,136 @@
#include "libaudcore/tuple.h"
#include "libaudcore/vfs.h"
-#define WMA_DEBUG 1
-
#define BROKEN 1
+enum {
+ GENRE_BLUES = 0,
+ GENRE_CLASSIC_ROCK,
+ GENRE_COUNTRY,
+ GENRE_DANCE,
+ GENRE_DISCO,
+ GENRE_FUNK,
+ GENRE_GRUNGE,
+ GENRE_HIPHOP,
+ GENRE_JAZZ,
+ GENRE_METAL,
+ GENRE_NEW_AGE,
+ GENRE_OLDIES,
+ GENRE_OTHER,
+ GENRE_POP,
+ GENRE_R_B,
+ GENRE_RAP,
+ GENRE_REGGAE,
+ GENRE_ROCK,
+ GENRE_TECHNO,
+ GENRE_INDUSTRIAL,
+ GENRE_ALTERNATIVE,
+ GENRE_SKA,
+ GENRE_DEATH_METAL,
+ GENRE_PRANKS,
+ GENRE_SOUNDTRACK,
+ GENRE_EURO_TECHNO,
+ GENRE_AMBIENT,
+ GENRE_TRIP_HOP,
+ GENRE_VOCAL,
+ GENRE_JAZZ_FUNK,
+ GENRE_FUSION,
+ GENRE_TRANCE,
+ GENRE_CLASSICAL,
+ GENRE_INSTRUMENTAL,
+ GENRE_ACID,
+ GENRE_HOUSE,
+ GENRE_GAME,
+ GENRE_SOUND_CLIP,
+ GENRE_GOSPEL,
+ GENRE_NOISE,
+ GENRE_ALTERNROCK,
+ GENRE_BASS,
+ GENRE_SOUL,
+ GENRE_PUNK,
+ GENRE_SPACE,
+ GENRE_MEDITATIVE,
+ GENRE_INSTRUMENTAL_POP,
+ GENRE_INSTRUMENTAL_ROCK,
+ GENRE_ETHNIC,
+ GENRE_GOTHIC,
+ GENRE_DARKWAVE,
+ GENRE_TECHNO_INDUSTRIAL,
+ GENRE_ELECTRONIC,
+ GENRE_POP_FOLK,
+ GENRE_EURODANCE,
+ GENRE_DREAM,
+ GENRE_SOUTHERN_ROCK,
+ GENRE_COMEDY,
+ GENRE_CULT,
+ GENRE_GANGSTA,
+ GENRE_TOP40,
+ GENRE_CHRISTIAN_RAP,
+ GENRE_POP_FUNK,
+ GENRE_JUNGLE,
+ GENRE_NATIVE_AMERICAN,
+ GENRE_CABARET,
+ GENRE_NEW_WAVE,
+ GENRE_PSYCHADELIC,
+ GENRE_RAVE,
+ GENRE_SHOWTUNES,
+ GENRE_TRAILER,
+ GENRE_LO_FI,
+ GENRE_TRIBAL,
+ GENRE_ACID_PUNK,
+ GENRE_ACID_JAZZ,
+ GENRE_POLKA,
+ GENRE_RETRO,
+ GENRE_MUSICAL,
+ GENRE_ROCK_ROLL,
+ GENRE_HARD_ROCK,
+ GENRE_FOLK,
+ GENRE_FOLK_ROCK,
+ GENRE_NATIONAL_FOLK,
+ GENRE_SWING,
+ GENRE_FAST_FUSION,
+ GENRE_BEBOB,
+ GENRE_LATIN,
+ GENRE_REVIVAL,
+ GENRE_CELTIC,
+ GENRE_BLUEGRASS,
+ GENRE_AVANTGARDE,
+ GENRE_GOTHIC_ROCK,
+ GENRE_PROGRESSIVE_ROCK,
+ GENRE_PSYCHEDELIC_ROCK,
+ GENRE_SYMPHONIC_ROCK,
+ GENRE_SLOW_ROCK,
+ GENRE_BIG_BAND,
+ GENRE_CHORUS,
+ GENRE_EASY_LISTENING,
+ GENRE_ACOUSTIC,
+ GENRE_HUMOUR,
+ GENRE_SPEECH,
+ GENRE_CHANSON,
+ GENRE_OPERA,
+ GENRE_CHAMBER_MUSIC,
+ GENRE_SONATA,
+ GENRE_SYMPHONY,
+ GENRE_BOOTY_BASS,
+ GENRE_PRIMUS,
+ GENRE_PORN_GROOVE,
+ GENRE_SATIRE,
+ GENRE_SLOW_JAM,
+ GENRE_CLUB,
+ GENRE_TANGO,
+ GENRE_SAMBA,
+ GENRE_FOLKLORE,
+ GENRE_BALLAD,
+ GENRE_POWER_BALLAD,
+ GENRE_RHYTHMIC_SOUL,
+ GENRE_FREESTYLE,
+ GENRE_DUET,
+ GENRE_PUNK_ROCK,
+ GENRE_DRUM_SOLO,
+ GENRE_A_CAPELLA,
+ GENRE_EURO_HOUSE
+};
+
time_t unix_time(guint64 win_time);
guint16 get_year(guint64 win_time);
@@ -50,9 +196,15 @@ gboolean write_LEuint64(VFSFile *fd, guint64 val);
guint64 read_LEint64(VFSFile *fd);
void copyAudioToFile(VFSFile *from, VFSFile *to, guint32 pos);
void copyAudioData(VFSFile* from, VFSFile *to, guint32 pos_from, guint32 pos_to);
+gboolean cut_beginning_tag (VFSFile * handle, gsize tag_size);
+
+gchar *convert_numericgenre_to_text(gint numericgenre);
+
+guint32 unsyncsafe32 (guint32 x);
+guint32 syncsafe32 (guint32 x);
/* macro for debug print */
-#ifdef WMA_DEBUG
+#ifdef DEBUG
# define AUDDBG(...) do { g_print("%s:%d %s(): ", __FILE__, (int)__LINE__, __FUNCTION__); g_print(__VA_ARGS__); } while (0)
#else
# define AUDDBG(...) do { } while (0)
diff --git a/src/libaudtag/wma/guid.c b/src/libaudtag/wma/guid.c
index 734b9ee..473c138 100644
--- a/src/libaudtag/wma/guid.c
+++ b/src/libaudtag/wma/guid.c
@@ -1,3 +1,23 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
/* this stuff may be moved to ../util.h if needed by other formats */
#include <inttypes.h>
@@ -7,10 +27,11 @@
#include "guid.h"
#include "wma_fmt.h"
-GUID * guid_read_from_file(VFSFile * f) {
+GUID *guid_read_from_file(VFSFile * f)
+{
GUID temp;
- if ((f == NULL) || (vfs_fread(&temp, sizeof (GUID), 1, f) != 1))
+ if ((f == NULL) || (vfs_fread(&temp, sizeof(GUID), 1, f) != 1))
return NULL;
temp.le32 = GUINT32_FROM_LE(temp.le32);
@@ -18,42 +39,40 @@ GUID * guid_read_from_file(VFSFile * f) {
temp.le16_2 = GUINT16_FROM_LE(temp.le16_2);
temp.be64 = GUINT64_FROM_BE(temp.be64);
- return g_memdup(& temp, sizeof (GUID));
+ return g_memdup(&temp, sizeof(GUID));
}
-gboolean guid_write_to_file(VFSFile * f, int guid_type) {
+gboolean guid_write_to_file(VFSFile * f, int guid_type)
+{
g_return_val_if_fail(f != NULL, FALSE);
GUID *g = guid_convert_from_string(wma_guid_map(guid_type));
- gboolean ret = write_LEuint32(f, g->le32) &&
- write_LEuint16(f, g->le16_1) &&
- write_LEuint16(f, g->le16_1) &&
- write_LEuint64(f, g->be64);
+ gboolean ret = write_LEuint32(f, g->le32) && write_LEuint16(f, g->le16_1) && write_LEuint16(f, g->le16_1) && write_LEuint64(f, g->be64);
g_free(g);
return ret;
}
-GUID *guid_convert_from_string(const gchar * string) {
+GUID *guid_convert_from_string(const gchar * string)
+{
GUID temp;
- if (sscanf(string, "%" SCNx32 "-%" SCNx16 "-%" SCNx16 "-%" SCNx64,
- & temp.le32, & temp.le16_1, & temp.le16_2, & temp.be64) != 4)
+ if (sscanf(string, "%" SCNx32 "-%" SCNx16 "-%" SCNx16 "-%" SCNx64, &temp.le32, &temp.le16_1, &temp.le16_2, &temp.be64) != 4)
return NULL;
- return g_memdup(& temp, sizeof (GUID));
+ return g_memdup(&temp, sizeof(GUID));
}
-gchar *guid_convert_to_string(const GUID* g) {
+gchar *guid_convert_to_string(const GUID * g)
+{
- return g_strdup_printf("%8x-%hx-%hx-%"PRIx64"\n", GUINT32_TO_LE(g->le32),
- GUINT16_TO_LE(g->le16_1), GUINT16_TO_LE(g->le16_2),
- GUINT64_TO_BE(g->be64));
+ return g_strdup_printf("%8x-%hx-%hx-%" PRIx64 "\n", GUINT32_TO_LE(g->le32), GUINT16_TO_LE(g->le16_1), GUINT16_TO_LE(g->le16_2), GUINT64_TO_BE(g->be64));
}
-gboolean guid_equal(GUID *g1, GUID *g2) {
+gboolean guid_equal(GUID * g1, GUID * g2)
+{
/*
- AUDDBG("GUID 1 = %8x-%hx-%hx-%"PRIx64"\n", g1->le32, g1->le16_1, g1->le16_2, g1->be64);
- AUDDBG("GUID 2 = %8x-%hx-%hx-%"PRIx64"\n", g2->le32, g2->le16_1, g2->le16_2, g2->be64);
+ AUDDBG("GUID 1 = %8x-%hx-%hx-%"PRIx64"\n", g1->le32, g1->le16_1, g1->le16_2, g1->be64);
+ AUDDBG("GUID 2 = %8x-%hx-%hx-%"PRIx64"\n", g2->le32, g2->le16_1, g2->le16_2, g2->be64);
*/
g_return_val_if_fail((g1 != NULL) && (g2 != NULL), FALSE);
@@ -67,7 +86,8 @@ gboolean guid_equal(GUID *g1, GUID *g2) {
return FALSE;
}
-int get_guid_type(GUID *g) {
+int get_guid_type(GUID * g)
+{
GUID *g1;
int i;
for (i = 0; i < ASF_OBJECT_LAST - 1; i++)
@@ -83,25 +103,26 @@ int get_guid_type(GUID *g) {
return -1;
}
-const gchar *wma_guid_map(int i) {
- const gchar * _guid_map[ASF_OBJECT_LAST] = {
- ASF_HEADER_OBJECT_GUID,
- ASF_FILE_PROPERTIES_OBJECT_GUID,
- ASF_STREAM_PROPERTIES_OBJECT_GUID,
- ASF_HEADER_EXTENSION_OBJECT_GUID,
- ASF_CODEC_LIST_OBJECT_GUID,
- ASF_SCRIPT_COMMAND_OBJECT_GUID,
- ASF_MARKER_OBJECT_GUID,
- ASF_BITRATE_MUTUAL_EXCLUSION_OBJECT_GUID,
- ASF_ERROR_CORRECTION_OBJECT_GUID,
- ASF_CONTENT_DESCRIPTION_OBJECT_GUID,
- ASF_EXTENDED_CONTENT_DESCRIPTION_OBJECT_GUID,
- ASF_CONTENT_BRANDING_OBJECT_GUID,
- ASF_STREAM_BITRATE_PROPERTIES_OBJECT_GUID,
- ASF_CONTENT_ENCRYPTION_OBJECT_GUID,
- ASF_EXTENDED_CONTENT_ENCRYPTION_OBJECT_GUID,
- ASF_DIGITAL_SIGNATURE_OBJECT_GUID,
- ASF_PADDING_OBJECT_GUID
+const gchar *wma_guid_map(int i)
+{
+ const gchar *_guid_map[ASF_OBJECT_LAST] = {
+ ASF_HEADER_OBJECT_GUID,
+ ASF_FILE_PROPERTIES_OBJECT_GUID,
+ ASF_STREAM_PROPERTIES_OBJECT_GUID,
+ ASF_HEADER_EXTENSION_OBJECT_GUID,
+ ASF_CODEC_LIST_OBJECT_GUID,
+ ASF_SCRIPT_COMMAND_OBJECT_GUID,
+ ASF_MARKER_OBJECT_GUID,
+ ASF_BITRATE_MUTUAL_EXCLUSION_OBJECT_GUID,
+ ASF_ERROR_CORRECTION_OBJECT_GUID,
+ ASF_CONTENT_DESCRIPTION_OBJECT_GUID,
+ ASF_EXTENDED_CONTENT_DESCRIPTION_OBJECT_GUID,
+ ASF_CONTENT_BRANDING_OBJECT_GUID,
+ ASF_STREAM_BITRATE_PROPERTIES_OBJECT_GUID,
+ ASF_CONTENT_ENCRYPTION_OBJECT_GUID,
+ ASF_EXTENDED_CONTENT_ENCRYPTION_OBJECT_GUID,
+ ASF_DIGITAL_SIGNATURE_OBJECT_GUID,
+ ASF_PADDING_OBJECT_GUID
};
return _guid_map[i];
}
diff --git a/src/libaudtag/wma/guid.h b/src/libaudtag/wma/guid.h
index e14284b..1bb193a 100644
--- a/src/libaudtag/wma/guid.h
+++ b/src/libaudtag/wma/guid.h
@@ -1,3 +1,23 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
#ifndef _GUID_H
#define _GUID_H
diff --git a/src/libaudtag/wma/module.h b/src/libaudtag/wma/module.h
index 99d9a6a..62670cb 100644
--- a/src/libaudtag/wma/module.h
+++ b/src/libaudtag/wma/module.h
@@ -1,6 +1,29 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
#ifndef TAG_WMA_MODULE_H
#define TAG_WMA_MODULE_H
#include "../tag_module.h"
+#include "wma.h"
+
extern tag_module_t wma;
+
#endif
diff --git a/src/libaudtag/wma/wma.c b/src/libaudtag/wma/wma.c
index 6605d16..67d5752 100644
--- a/src/libaudtag/wma/wma.c
+++ b/src/libaudtag/wma/wma.c
@@ -1,3 +1,23 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
#include <inttypes.h>
#include <glib-2.0/glib/gstdio.h>
#include <libaudcore/tuple.h>
@@ -8,17 +28,16 @@
#include "module.h"
#include "../util.h"
-tag_module_t wma = {wma_can_handle_file, wma_populate_tuple_from_file, wma_write_tuple_to_file};
-
/* static functions */
-static GenericHeader *read_generic_header(VFSFile*f, gboolean read_data) {
+static GenericHeader *read_generic_header(VFSFile * f, gboolean read_data)
+{
AUDDBG("read top-level header object\n");
g_return_val_if_fail((f != NULL), NULL);
GenericHeader *header = g_new0(GenericHeader, 1);
header->guid = guid_read_from_file(f);
header->size = read_LEuint64(f);
if (read_data)
- header->data = (gchar*) read_char_data(f, header->size);
+ header->data = (gchar *) read_char_data(f, header->size);
else
header->data = NULL;
@@ -29,7 +48,8 @@ static GenericHeader *read_generic_header(VFSFile*f, gboolean read_data) {
return header;
}
-static HeaderObj *read_top_header_object(VFSFile *f) {
+static HeaderObj *read_top_header_object(VFSFile * f)
+{
AUDDBG("read top-level header object\n");
g_return_val_if_fail((f != NULL), NULL);
HeaderObj *header = g_new0(HeaderObj, 1);
@@ -52,7 +72,8 @@ static HeaderObj *read_top_header_object(VFSFile *f) {
return header;
}
-static ContentDescrObj *read_content_descr_obj(VFSFile *f) {
+static ContentDescrObj *read_content_descr_obj(VFSFile * f)
+{
ContentDescrObj *cdo = g_new0(ContentDescrObj, 1);
cdo->guid = guid_read_from_file(f);
cdo->size = read_LEuint64(f);
@@ -69,7 +90,8 @@ static ContentDescrObj *read_content_descr_obj(VFSFile *f) {
return cdo;
}
-static ExtContentDescrObj *read_ext_content_descr_obj(VFSFile *f, Tuple* t, gboolean populate_tuple) {
+static ExtContentDescrObj *read_ext_content_descr_obj(VFSFile * f, Tuple * t, gboolean populate_tuple)
+{
ExtContentDescrObj *ecdo = g_new0(ExtContentDescrObj, 1);
ecdo->guid = guid_read_from_file(f);
ecdo->size = read_LEuint64(f);
@@ -78,10 +100,11 @@ static ExtContentDescrObj *read_ext_content_descr_obj(VFSFile *f, Tuple* t, gboo
return ecdo;
}
-static guint find_descriptor_id(gchar* s) {
+static guint find_descriptor_id(gchar * s)
+{
AUDDBG("finding descriptor id for '%s'\n", s);
g_return_val_if_fail(s != NULL, -1);
- gchar * l[DESC_LAST] = {DESC_ALBUM_STR, DESC_YEAR_STR, DESC_GENRE_STR, DESC_TRACK_STR};
+ gchar *l[DESC_LAST] = { DESC_ALBUM_STR, DESC_YEAR_STR, DESC_GENRE_STR, DESC_TRACK_STR };
guint i;
for (i = 0; i < DESC_LAST; i++)
if (!strcmp(l[i], s))
@@ -92,7 +115,8 @@ static guint find_descriptor_id(gchar* s) {
return -1;
}
-static ContentDescriptor *read_descriptor(VFSFile *f, Tuple *t, gboolean populate_tuple) {
+static ContentDescriptor *read_descriptor(VFSFile * f, Tuple * t, gboolean populate_tuple)
+{
ContentDescriptor *cd = g_new0(ContentDescriptor, 1);
gchar *val = NULL, *name = NULL;
guint32 intval = -1;
@@ -114,9 +138,9 @@ static ContentDescriptor *read_descriptor(VFSFile *f, Tuple *t, gboolean populat
if (populate_tuple)
{
- /*we only parse int's and UTF strings, everything else is handled as raw data*/
+ /*we only parse int's and UTF strings, everything else is handled as raw data */
if (cd->val_type == 0)
- {/*UTF16*/
+ { /*UTF16 */
cd->val = read_char_data(f, cd->val_len);
val = utf8((gunichar2 *) cd->val);
AUDDBG("val: '%s' dtype: %d\n", val, dtype);
@@ -128,7 +152,8 @@ static ContentDescriptor *read_descriptor(VFSFile *f, Tuple *t, gboolean populat
tuple_associate_int(t, FIELD_TRACK_NUMBER, NULL, atoi(val));
if (dtype == DESC_YEAR)
tuple_associate_int(t, FIELD_YEAR, NULL, atoi(val));
- } else
+ }
+ else
{
if (cd->val_type == 3)
{
@@ -136,27 +161,31 @@ static ContentDescriptor *read_descriptor(VFSFile *f, Tuple *t, gboolean populat
AUDDBG("intval: %d, dtype: %d\n", intval, dtype);
if (dtype == DESC_TRACK)
tuple_associate_int(t, FIELD_TRACK_NUMBER, NULL, intval);
- } else
+ }
+ else
cd->val = read_char_data(f, cd->val_len);
}
- } else
+ }
+ else
cd->val = read_char_data(f, cd->val_len);
AUDDBG("read str_val: '%s', intval: %d\n", val, intval);
AUDDBG("exiting read_descriptor \n\n");
return cd;
}
-static ContentDescriptor **read_descriptors(VFSFile *f, guint count, Tuple* t, gboolean populate_tuple) {
+static ContentDescriptor **read_descriptors(VFSFile * f, guint count, Tuple * t, gboolean populate_tuple)
+{
if (count == 0)
return NULL;
- ContentDescriptor **descs = g_new0(ContentDescriptor*, count);
+ ContentDescriptor **descs = g_new0(ContentDescriptor *, count);
int i;
for (i = 0; i < count; i++)
descs[i] = read_descriptor(f, t, populate_tuple);
return descs;
}
-void free_content_descr_obj(ContentDescrObj* c) {
+void free_content_descr_obj(ContentDescrObj * c)
+{
g_free(c->guid);
g_free(c->title);
g_free(c->author);
@@ -166,13 +195,15 @@ void free_content_descr_obj(ContentDescrObj* c) {
g_free(c);
}
-void free_content_descr(ContentDescriptor *cd) {
+void free_content_descr(ContentDescriptor * cd)
+{
g_free(cd->name);
g_free(cd->val);
g_free(cd);
}
-void free_ext_content_descr_obj(ExtContentDescrObj *ecdo) {
+void free_ext_content_descr_obj(ExtContentDescrObj * ecdo)
+{
int i;
g_free(ecdo->guid);
for (i = 0; i < ecdo->content_desc_count; i++)
@@ -181,7 +212,8 @@ void free_ext_content_descr_obj(ExtContentDescrObj *ecdo) {
}
/* returns the offset of the object in the file */
-static long ftell_object_by_guid(VFSFile *f, GUID *g) {
+static long ftell_object_by_guid(VFSFile * f, GUID * g)
+{
AUDDBG("seeking object %s, with ID %d \n", guid_convert_to_string(g), get_guid_type(g));
HeaderObj *h = read_top_header_object(f);
g_return_val_if_fail((f != NULL) && (g != NULL) && (h != NULL), -1);
@@ -190,17 +222,16 @@ static long ftell_object_by_guid(VFSFile *f, GUID *g) {
while (i < h->objectsNr)
{
GenericHeader *gen_hdr = read_generic_header(f, FALSE);
- AUDDBG("encountered GUID %s, with ID %d\n",
- guid_convert_to_string(gen_hdr->guid), get_guid_type(gen_hdr->guid));
+ AUDDBG("encountered GUID %s, with ID %d\n", guid_convert_to_string(gen_hdr->guid), get_guid_type(gen_hdr->guid));
if (guid_equal(gen_hdr->guid, g))
{
g_free(h);
g_free(gen_hdr);
guint64 ret = vfs_ftell(f) - 24;
- AUDDBG("at offset %"PRIx64"\n", ret);
+ AUDDBG("at offset %" PRIx64 "\n", ret);
return ret;
}
- vfs_fseek(f, gen_hdr->size - 24, SEEK_CUR); //most headers have a size as their second field"
+ vfs_fseek(f, gen_hdr->size - 24, SEEK_CUR); //most headers have a size as their second field"
i++;
}
AUDDBG("The object was not found\n");
@@ -208,21 +239,24 @@ static long ftell_object_by_guid(VFSFile *f, GUID *g) {
return -1;
}
-VFSFile *make_temp_file() {
- /* create a temporary file*/
+VFSFile *make_temp_file()
+{
+ /* create a temporary file */
const gchar *tmpdir = g_get_tmp_dir();
gchar *tmp_path = g_strdup_printf("file://%s/%s", tmpdir, "wmatmp.wma");
return vfs_fopen(tmp_path, "w+");
}
-long ftell_object_by_str(VFSFile *f, gchar *s) {
- GUID* g = guid_convert_from_string(s);
+long ftell_object_by_str(VFSFile * f, gchar * s)
+{
+ GUID *g = guid_convert_from_string(s);
long res = ftell_object_by_guid(f, g);
g_free(g);
return res;
}
-static void write_content_descr_obj_from_tuple(VFSFile *f, ContentDescrObj *cdo, Tuple* t) {
+static void write_content_descr_obj_from_tuple(VFSFile * f, ContentDescrObj * cdo, Tuple * t)
+{
glong size;
gboolean free_cdo = FALSE;
if (cdo == NULL)
@@ -231,66 +265,64 @@ static void write_content_descr_obj_from_tuple(VFSFile *f, ContentDescrObj *cdo,
free_cdo = TRUE;
}
- cdo->title = g_utf8_to_utf16(tuple_get_string(t, FIELD_TITLE, NULL),
- -1, NULL, &size, NULL);
+ cdo->title = g_utf8_to_utf16(tuple_get_string(t, FIELD_TITLE, NULL), -1, NULL, &size, NULL);
cdo->title_length = 2 * (size + 1);
- cdo->author = g_utf8_to_utf16(tuple_get_string(t, FIELD_ARTIST, NULL),
- -1, NULL, &size, NULL);
+ cdo->author = g_utf8_to_utf16(tuple_get_string(t, FIELD_ARTIST, NULL), -1, NULL, &size, NULL);
cdo->author_length = 2 * (size + 1);
- cdo->copyright = g_utf8_to_utf16(tuple_get_string(t, FIELD_COPYRIGHT, NULL),
- -1, NULL, &size, NULL);
+ cdo->copyright = g_utf8_to_utf16(tuple_get_string(t, FIELD_COPYRIGHT, NULL), -1, NULL, &size, NULL);
cdo->copyright_length = 2 * (size + 1);
- cdo->description = g_utf8_to_utf16(tuple_get_string(t, FIELD_COMMENT, NULL),
- -1, NULL, &size, NULL);
+ cdo->description = g_utf8_to_utf16(tuple_get_string(t, FIELD_COMMENT, NULL), -1, NULL, &size, NULL);
cdo->desc_length = 2 * (size + 1);
- cdo->size = 34 + cdo->title_length + cdo->author_length +
- cdo->copyright_length + cdo->desc_length;
+ cdo->size = 34 + cdo->title_length + cdo->author_length + cdo->copyright_length + cdo->desc_length;
guid_write_to_file(f, ASF_CONTENT_DESCRIPTION_OBJECT);
write_LEuint64(f, cdo->size);
write_LEuint16(f, cdo->title_length);
write_LEuint16(f, cdo->author_length);
write_LEuint16(f, cdo->copyright_length);
write_LEuint16(f, cdo->desc_length);
- write_LEuint16(f, 2); // rating_length = 2
+ write_LEuint16(f, 2); // rating_length = 2
write_utf16(f, cdo->title, cdo->title_length);
write_utf16(f, cdo->title, cdo->title_length);
write_utf16(f, cdo->author, cdo->author_length);
write_utf16(f, cdo->copyright, cdo->copyright_length);
write_utf16(f, cdo->description, cdo->desc_length);
- write_utf16(f, NULL, 2); //rating == NULL
+ write_utf16(f, NULL, 2); //rating == NULL
if (free_cdo)
free_content_descr_obj(cdo);
}
-static void write_ext_content_descr_obj_from_tuple(VFSFile *f, ExtContentDescrObj* ecdo, Tuple* tuple) { }
+static void write_ext_content_descr_obj_from_tuple(VFSFile * f, ExtContentDescrObj * ecdo, Tuple * tuple)
+{
+}
-static gboolean write_generic_header(VFSFile *f, GenericHeader *gh) {
+static gboolean write_generic_header(VFSFile * f, GenericHeader * gh)
+{
AUDDBG("Writing generic header\n");
guid_write_to_file(f, get_guid_type(gh->guid));
return write_char_data(f, gh->data, gh->size);
}
-static void free_generic_header(GenericHeader *gh) {
+static void free_generic_header(GenericHeader * gh)
+{
g_free(gh->guid);
g_free(gh->data);
g_free(gh);
}
-static gboolean write_top_header_object(VFSFile *f, HeaderObj *header) {
+static gboolean write_top_header_object(VFSFile * f, HeaderObj * header)
+{
AUDDBG("write header object\n");
vfs_fseek(f, 0, SEEK_SET);
- return (guid_write_to_file(f, ASF_HEADER_OBJECT) &&
- write_LEuint64(f, header->size) &&
- write_LEuint32(f, header->objectsNr) &&
- write_uint8(f, header->res1) && /* the reserved fields*/
+ return (guid_write_to_file(f, ASF_HEADER_OBJECT) && write_LEuint64(f, header->size) && write_LEuint32(f, header->objectsNr) && write_uint8(f, header->res1) && /* the reserved fields */
write_uint8(f, header->res2));
}
/* interface functions */
-gboolean wma_can_handle_file(VFSFile *f) {
- GUID * guid1 = guid_read_from_file(f);
- GUID * guid2 = guid_convert_from_string(ASF_HEADER_OBJECT_GUID);
+gboolean wma_can_handle_file(VFSFile * f)
+{
+ GUID *guid1 = guid_read_from_file(f);
+ GUID *guid2 = guid_convert_from_string(ASF_HEADER_OBJECT_GUID);
gboolean equal = ((guid1 != NULL) && guid_equal(guid1, guid2));
g_free(guid1);
@@ -299,13 +331,14 @@ gboolean wma_can_handle_file(VFSFile *f) {
return equal;
}
-Tuple *wma_populate_tuple_from_file(Tuple *t, VFSFile *f) {
+gboolean wma_read_tag (Tuple * t, VFSFile * f)
+{
gchar *artist = NULL, *title = NULL, *comment = NULL;
print_tuple(t);
gint seek_res = vfs_fseek(f, ftell_object_by_str(f, ASF_CONTENT_DESCRIPTION_OBJECT_GUID), SEEK_SET);
if (seek_res == 0)
- { //if the CONTENT_DESCRIPTION_OBJECT was found
+ { //if the CONTENT_DESCRIPTION_OBJECT was found
ContentDescrObj *cdo = read_content_descr_obj(f);
artist = utf8(cdo->author);
title = utf8(cdo->title);
@@ -316,27 +349,26 @@ Tuple *wma_populate_tuple_from_file(Tuple *t, VFSFile *f) {
tuple_associate_string(t, FIELD_COMMENT, NULL, comment);
}
seek_res = vfs_fseek(f, ftell_object_by_str(f, ASF_EXTENDED_CONTENT_DESCRIPTION_OBJECT_GUID), SEEK_SET);
- /*this populates the tuple with the attributes stored as extended descriptors*/
+ /*this populates the tuple with the attributes stored as extended descriptors */
ExtContentDescrObj *ecdo = read_ext_content_descr_obj(f, t, TRUE);
free_ext_content_descr_obj(ecdo);
print_tuple(t);
- return t;
+ return TRUE;
}
-gboolean wma_write_tuple_to_file(Tuple *tuple, VFSFile *f) {
-
-
+gboolean wma_write_tag (Tuple * tuple, VFSFile * f)
+{
#if BROKEN
return FALSE;
#endif
HeaderObj *top_ho = read_top_header_object(f);
- VFSFile * tmpfile = make_temp_file();
+ VFSFile *tmpfile = make_temp_file();
gint i, cdo_pos, ecdo_pos;
- GUID* g;
- /*read all the headers and write them to the new file*/
- /*the headers that contain tuple data will be overwritten*/
- AUDDBG("Header Object size: %"PRId64"\n", top_ho->size);
+ GUID *g;
+ /*read all the headers and write them to the new file */
+ /*the headers that contain tuple data will be overwritten */
+ AUDDBG("Header Object size: %" PRId64 "\n", top_ho->size);
//vfs_fseek(tmpfile, )
for (i = 0; i < top_ho->objectsNr; i++)
{
@@ -344,13 +376,14 @@ gboolean wma_write_tuple_to_file(Tuple *tuple, VFSFile *f) {
g = guid_convert_from_string(ASF_CONTENT_DESCRIPTION_OBJECT_GUID);
if (guid_equal(gh->guid, g))
{
- write_content_descr_obj_from_tuple(tmpfile, (ContentDescrObj*) gh, tuple);
+ write_content_descr_obj_from_tuple(tmpfile, (ContentDescrObj *) gh, tuple);
g_free(g);
- } else
+ }
+ else
{
g = guid_convert_from_string(ASF_EXTENDED_CONTENT_DESCRIPTION_OBJECT_GUID);
if (guid_equal(gh->guid, g))
- write_ext_content_descr_obj_from_tuple(tmpfile, (ExtContentDescrObj*) gh, tuple);
+ write_ext_content_descr_obj_from_tuple(tmpfile, (ExtContentDescrObj *) gh, tuple);
else
{
write_generic_header(tmpfile, gh);
@@ -359,7 +392,7 @@ gboolean wma_write_tuple_to_file(Tuple *tuple, VFSFile *f) {
}
free_generic_header(gh);
}
- /*check wether these headers existed in the original file*/
+ /*check wether these headers existed in the original file */
cdo_pos = ftell_object_by_str(f, ASF_CONTENT_DESCRIPTION_OBJECT_GUID);
ecdo_pos = ftell_object_by_str(f, ASF_EXTENDED_CONTENT_DESCRIPTION_OBJECT_GUID);
if (cdo_pos == -1)
@@ -374,21 +407,29 @@ gboolean wma_write_tuple_to_file(Tuple *tuple, VFSFile *f) {
}
write_top_header_object(tmpfile, top_ho);
- gchar* f1 = g_filename_from_uri(tmpfile->uri, NULL, NULL);
- gchar* f2 = g_filename_from_uri(f->uri, NULL, NULL);
+ gchar *f1 = g_filename_from_uri(tmpfile->uri, NULL, NULL);
+ gchar *f2 = g_filename_from_uri(f->uri, NULL, NULL);
vfs_fclose(tmpfile);
/*
- if (g_rename(f1, f2) == 0)
- {
- AUDDBG("the tag was updated successfully\n");
- }
- else
- {
- AUDDBG("an error has occured\n");
- }
+ if (g_rename(f1, f2) == 0)
+ {
+ AUDDBG("the tag was updated successfully\n");
+ }
+ else
+ {
+ AUDDBG("an error has occured\n");
+ }
*/
g_free(f1);
g_free(f2);
return TRUE;
}
+
+tag_module_t wma = {
+ .name = "WMA",
+ .can_handle_file = wma_can_handle_file,
+ .read_tag = wma_read_tag,
+ .write_tag = wma_write_tag,
+};
+
diff --git a/src/libaudtag/wma/wma.h b/src/libaudtag/wma/wma.h
index 9b45d08..756cee2 100644
--- a/src/libaudtag/wma/wma.h
+++ b/src/libaudtag/wma/wma.h
@@ -1,3 +1,23 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
#ifndef _WMA_H
#define _WMA_H
@@ -6,6 +26,7 @@
#include "libaudcore/vfs.h"
#include "wma_fmt.h"
+#ifndef TAG_WMA_MODULE_H
/* static functions */
/* reads the whole structure, containing the data */
@@ -23,13 +44,11 @@ static ExtContentDescrObj *read_ext_content_descr_obj(VFSFile * f, Tuple *t, gbo
static long ftell_object_by_guid(VFSFile *f, GUID *g);
static long ftell_object_by_str(VFSFile *f, gchar *s);
+#endif
-/* interface functions*/
+/* TAG plugin API */
gboolean wma_can_handle_file(VFSFile *f);
-
-Tuple *wma_populate_tuple_from_file(Tuple *t, VFSFile *f);
-
-gboolean wma_write_tuple_to_file(Tuple *t, VFSFile *f);
+gboolean wma_read_tag (Tuple * tuple, VFSFile * handle);
+gboolean wma_write_tag (Tuple * tuple, VFSFile * handle);
#endif /* _WMA_H */
-
diff --git a/src/libaudtag/wma/wma_fmt.h b/src/libaudtag/wma/wma_fmt.h
index 3b6bf64..c96517c 100644
--- a/src/libaudtag/wma/wma_fmt.h
+++ b/src/libaudtag/wma/wma_fmt.h
@@ -1,3 +1,23 @@
+/*
+ * Copyright 2009 Paula Stanciu
+ *
+ * This file is part of Audacious.
+ *
+ * Audacious 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, version 3 of the License.
+ *
+ * Audacious is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * Audacious. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * The Audacious team does not consider modular code linking to Audacious or
+ * using our public API to be a derived work.
+ */
+
#ifndef _WMA_FMT_H
#define _WMA_FMT_H
@@ -56,7 +76,7 @@ typedef enum {
DESC_LAST
} DescrIndexes;
-/*
+/*
* this should be fine for all headers whose content is irrelevant,
* but the size is needed so that we can skip it
*/
diff --git a/src/libeggsmclient/Makefile b/src/libeggsmclient/Makefile
index fbe40e7..b124d60 100644
--- a/src/libeggsmclient/Makefile
+++ b/src/libeggsmclient/Makefile
@@ -18,4 +18,4 @@ include ../../buildsys.mk
include ../../extra.mk
CPPFLAGS += ${INCLUDES} ${GLIB_CFLAGS} ${GTK_CFLAGS} -I../.. -I. -I../audacious/platform ${platform_defines}
-LIBS += ${GLIB_LIBS} ${GTK_LIBS} ${platform_libs}
+LIBS += ${GLIB_LIBS} ${GTK_LIBS} ${ICE_LIBS} ${platform_libs}
diff --git a/src/libguess/Makefile b/src/libguess/Makefile
index a21558d..e2f6937 100644
--- a/src/libguess/Makefile
+++ b/src/libguess/Makefile
@@ -5,6 +5,7 @@ SRCS = guess.c \
greek_impl.c \
hebrew_impl.c \
russian_impl.c \
- turkish_impl.c
+ turkish_impl.c \
+ polish_impl.c
include ../../buildsys.mk
diff --git a/src/libguess/guess.c b/src/libguess/guess.c
index b7e2ef0..847972e 100644
--- a/src/libguess/guess.c
+++ b/src/libguess/guess.c
@@ -35,6 +35,7 @@ void guess_init(void)
guess_impl_register(GUESS_REGION_TR, guess_tr);
guess_impl_register(GUESS_REGION_GR, guess_gr);
guess_impl_register(GUESS_REGION_HW, guess_hw);
+ guess_impl_register(GUESS_REGION_PL, guess_pl);
}
const char *guess_encoding(const char *inbuf, int buflen, const char *lang)
diff --git a/src/libguess/libguess.h b/src/libguess/libguess.h
index 4a634d0..1528f0a 100644
--- a/src/libguess/libguess.h
+++ b/src/libguess/libguess.h
@@ -51,6 +51,7 @@ const char *guess_ar(const char *buf, int buflen);
const char *guess_tr(const char *buf, int buflen);
const char *guess_gr(const char *buf, int buflen);
const char *guess_hw(const char *buf, int buflen);
+const char *guess_pl(const char *buf, int buflen);
int dfa_validate_utf8(const char *buf, int buflen);
#define GUESS_REGION_JP "japanese"
@@ -62,6 +63,7 @@ int dfa_validate_utf8(const char *buf, int buflen);
#define GUESS_REGION_TR "turkish"
#define GUESS_REGION_GR "greek"
#define GUESS_REGION_HW "hebrew"
+#define GUESS_REGION_PL "polish"
const char *guess_encoding(const char *buf, int buflen, const char *lang);
void guess_init(void);
diff --git a/src/libguess/polish_impl.c b/src/libguess/polish_impl.c
new file mode 100644
index 0000000..b72cfcb
--- /dev/null
+++ b/src/libguess/polish_impl.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2010 Michał Lipski <tallica@o2.pl>
+ *
+ * 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+static const char *_guess_pl(const unsigned char *ptr, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++)
+ {
+ if (ptr[i] == 0xB9 || //ą
+ ptr[i] == 0xE6 || //ć
+ ptr[i] == 0xEA || //ę
+ ptr[i] == 0xB3 || //ł
+ ptr[i] == 0xF1 || //ń
+ ptr[i] == 0xF3 || //ó
+ ptr[i] == 0x9C || //ś
+ ptr[i] == 0x9F || //ź
+ ptr[i] == 0xBF || //ż
+ ptr[i] == 0xA5 || //Ą
+ ptr[i] == 0xC6 || //Ć
+ ptr[i] == 0xCA || //Ę
+ ptr[i] == 0xA3 || //Ł
+ ptr[i] == 0xD1 || //Ń
+ ptr[i] == 0xD3 || //Ó
+ ptr[i] == 0x8C || //Ś
+ ptr[i] == 0x8F || //Ź
+ ptr[i] == 0xAF) //Ż
+
+ return "CP1250";
+ }
+
+ return "ISO-8859-2";
+}
+
+const char *guess_pl(const char *ptr, int size)
+{
+ return _guess_pl((const unsigned char *) ptr, size);
+}
diff --git a/src/libid3tag/Makefile b/src/libid3tag/Makefile
deleted file mode 100644
index 1a49ef9..0000000
--- a/src/libid3tag/Makefile
+++ /dev/null
@@ -1,34 +0,0 @@
-LIB = ${LIB_PREFIX}audid3tag${LIB_SUFFIX}
-LIB_MAJOR = 2
-LIB_MINOR = 0
-
-LIBDIR = ${plugindir}
-
-INCLUDES = id3tag.h
-
-SRCS = compat.c \
- debug.c \
- file.c \
- frametype.c \
- latin1.c \
- render.c \
- ucs4.c \
- utf8.c \
- version.c \
- crc.c \
- field.c \
- frame.c \
- genre.c \
- parse.c \
- tag.c \
- utf16.c \
- util.c
-
-include ../../buildsys.mk
-include ../../extra.mk
-
-CPPFLAGS += ${LIB_CPPFLAGS} -I.. ${GLIB_CFLAGS} ${GTK_CFLAGS} \
- ${MOWGLI_CFLAGS} ${LIBMCS_CFLAGS}
-
-CFLAGS += ${LIB_CFLAGS}
-LIBS += -lz ${GLIB_LIBS}
diff --git a/src/libid3tag/README.audacious b/src/libid3tag/README.audacious
deleted file mode 100644
index 4ea0ebe..0000000
--- a/src/libid3tag/README.audacious
+++ /dev/null
@@ -1,9 +0,0 @@
-The sources in libid3tag are heavily modified by the Audacious team for
-use in Audacious. If you are a package maintainer, please do not patch
-out this library as Audacious needs the modifications made here.
-
-The modifications are as follows:
- - use the Audacious VFS subsystem for stream I/O instead of libc
- - add support for opening an id3 tagged file from a live VFS handle.
- - some minor portability improvements
-
diff --git a/src/libid3tag/compat.c b/src/libid3tag/compat.c
deleted file mode 100644
index 0b22d7c..0000000
--- a/src/libid3tag/compat.c
+++ /dev/null
@@ -1,412 +0,0 @@
-/* C code produced by gperf version 2.7 */
-/* Command-line: gperf -tCcTonD -K id -N id3_compat_lookup -s -3 -k * compat.gperf */
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Id: compat.gperf,v 1.11 2004/01/23 09:41:32 rob Exp
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <stdlib.h>
-# include <string.h>
-
-# ifdef HAVE_ASSERT_H
-# include <assert.h>
-# endif
-
-# include "id3tag.h"
-# include "compat.h"
-# include "frame.h"
-# include "field.h"
-# include "parse.h"
-# include "ucs4.h"
-
-# define EQ(id) #id, 0
-# define OBSOLETE 0, 0
-# define TX(id) #id, translate_##id
-
-static id3_compat_func_t translate_TCON;
-
-#define TOTAL_KEYWORDS 73
-#define MIN_WORD_LENGTH 3
-#define MAX_WORD_LENGTH 4
-#define MIN_HASH_VALUE 1
-#define MAX_HASH_VALUE 84
-/* maximum key range = 84, duplicates = 10 */
-
-#ifdef __GNUC__
-__inline
-#endif
-static unsigned int
-hash (str, len)
- register const char *str;
- register unsigned int len;
-{
- static const unsigned char asso_values[] =
- {
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 22,
- 21, 27, 26, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 9, 3, 0, 27, 16,
- 6, 30, 85, 15, 85, 22, 2, 15, 4, 1,
- 0, 30, 13, 17, 22, 0, 24, 5, 31, 25,
- 15, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85, 85, 85, 85, 85,
- 85, 85, 85, 85, 85, 85
- };
- register int hval = 0;
-
- switch (len)
- {
- default:
- case 4:
- hval += asso_values[(unsigned char)str[3]];
- case 3:
- hval += asso_values[(unsigned char)str[2]];
- case 2:
- hval += asso_values[(unsigned char)str[1]];
- case 1:
- hval += asso_values[(unsigned char)str[0]];
- break;
- }
- return hval;
-}
-
-#ifdef __GNUC__
-__inline
-#endif
-const struct id3_compat *
-id3_compat_lookup (str, len)
- register const char *str;
- register unsigned int len;
-{
- static const struct id3_compat wordlist[] =
- {
- {"POP", EQ(POPM) /* Popularimeter */},
- {"WCP", EQ(WCOP) /* Copyright/legal information */},
- {"WPB", EQ(WPUB) /* Publishers official webpage */},
- {"BUF", EQ(RBUF) /* Recommended buffer size */},
- {"PIC", EQ(APIC) /* Attached picture */},
- {"COM", EQ(COMM) /* Comments */},
- {"IPL", EQ(TIPL) /* Involved people list */},
- {"MLL", EQ(MLLT) /* MPEG location lookup table */},
- {"WAF", EQ(WOAF) /* Official audio file webpage */},
- {"WCM", EQ(WCOM) /* Commercial information */},
- {"UFI", EQ(UFID) /* Unique file identifier */},
- {"CRA", EQ(AENC) /* Audio encryption */},
- {"TCO", TX(TCON) /* Content type */},
- {"ULT", EQ(USLT) /* Unsynchronised lyric/text transcription */},
- {"TOL", EQ(TOLY) /* Original lyricist(s)/text writer(s) */},
- {"TBP", EQ(TBPM) /* BPM (beats per minute) */},
- {"TPB", EQ(TPUB) /* Publisher */},
- {"CNT", EQ(PCNT) /* Play counter */},
- {"TCON", TX(TCON) /* Content type */},
- {"WAR", EQ(WOAR) /* Official artist/performer webpage */},
- {"LNK", EQ(LINK) /* Linked information */},
- {"CRM", OBSOLETE /* Encrypted meta frame [obsolete] */},
- {"TOF", EQ(TOFN) /* Original filename */},
- {"MCI", EQ(MCDI) /* Music CD identifier */},
- {"TPA", EQ(TPOS) /* Part of a set */},
- {"WAS", EQ(WOAS) /* Official audio source webpage */},
- {"TOA", EQ(TOPE) /* Original artist(s)/performer(s) */},
- {"TAL", EQ(TALB) /* Album/movie/show title */},
- {"TLA", EQ(TLAN) /* Language(s) */},
- {"IPLS", EQ(TIPL) /* Involved people list */},
- {"TCR", EQ(TCOP) /* Copyright message */},
- {"TRC", EQ(TSRC) /* ISRC (international standard recording code) */},
- {"TOR", EQ(TDOR) /* Original release year [obsolete] */},
- {"TCM", EQ(TCOM) /* Composer */},
- {"ETC", EQ(ETCO) /* Event timing codes */},
- {"STC", EQ(SYTC) /* Synchronised tempo codes */},
- {"TLE", EQ(TLEN) /* Length */},
- {"SLT", EQ(SYLT) /* Synchronised lyric/text */},
- {"TEN", EQ(TENC) /* Encoded by */},
- {"TP2", EQ(TPE2) /* Band/orchestra/accompaniment */},
- {"TP1", EQ(TPE1) /* Lead performer(s)/soloist(s) */},
- {"TOT", EQ(TOAL) /* Original album/movie/show title */},
- {"EQU", OBSOLETE /* Equalization [obsolete] */},
- {"RVA", OBSOLETE /* Relative volume adjustment [obsolete] */},
- {"GEO", EQ(GEOB) /* General encapsulated object */},
- {"TP4", EQ(TPE4) /* Interpreted, remixed, or otherwise modified by */},
- {"TP3", EQ(TPE3) /* Conductor/performer refinement */},
- {"TFT", EQ(TFLT) /* File type */},
- {"TIM", OBSOLETE /* Time [obsolete] */},
- {"REV", EQ(RVRB) /* Reverb */},
- {"TSI", OBSOLETE /* Size [obsolete] */},
- {"EQUA", OBSOLETE /* Equalization [obsolete] */},
- {"TSS", EQ(TSSE) /* Software/hardware and settings used for encoding */},
- {"TRK", EQ(TRCK) /* Track number/position in set */},
- {"TDA", OBSOLETE /* Date [obsolete] */},
- {"TMT", EQ(TMED) /* Media type */},
- {"TKE", EQ(TKEY) /* Initial key */},
- {"TORY", EQ(TDOR) /* Original release year [obsolete] */},
- {"TRD", OBSOLETE /* Recording dates [obsolete] */},
- {"TYE", OBSOLETE /* Year [obsolete] */},
- {"TT2", EQ(TIT2) /* Title/songname/content description */},
- {"TT1", EQ(TIT1) /* Content group description */},
- {"WXX", EQ(WXXX) /* User defined URL link frame */},
- {"TIME", OBSOLETE /* Time [obsolete] */},
- {"TSIZ", OBSOLETE /* Size [obsolete] */},
- {"TT3", EQ(TIT3) /* Subtitle/description refinement */},
- {"TRDA", OBSOLETE /* Recording dates [obsolete] */},
- {"RVAD", OBSOLETE /* Relative volume adjustment [obsolete] */},
- {"TDY", EQ(TDLY) /* Playlist delay */},
- {"TXT", EQ(TEXT) /* Lyricist/text writer */},
- {"TYER", OBSOLETE /* Year [obsolete] */},
- {"TDAT", OBSOLETE /* Date [obsolete] */},
- {"TXX", EQ(TXXX) /* User defined text information frame */}
- };
-
- static const short lookup[] =
- {
- -1, 0, -1, -53, -2, 1, -49, -2,
- 2, 3, -1, -46, -2, -43, -2, 4,
- 5, 6, -1, 7, -163, 10, 11, 12,
- 13, -161, 17, -159, -77, 22, 23, -80,
- 26, -85, 29, -87, 32, 33, 34, 35,
- 36, 37, 38, 39, 40, 41, -155, 44,
- 45, 46, 47, -1, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, 57, 58, 59,
- -1, 60, 61, 62, 63, 64, -1, -151,
- -1, 67, 68, 69, 70, -8, -2, -1,
- 71, -31, -2, -1, 72, -55, -2, -59,
- -3, -65, -2
- };
-
- if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
- {
- register int key = hash (str, len);
-
- if (key <= MAX_HASH_VALUE && key >= 0)
- {
- register int index = lookup[key];
-
- if (index >= 0)
- {
- register const char *s = wordlist[index].id;
-
- if (*str == *s && !strncmp (str + 1, s + 1, len - 1))
- return &wordlist[index];
- }
- else if (index < -TOTAL_KEYWORDS)
- {
- register int offset = - 1 - TOTAL_KEYWORDS - index;
- register const struct id3_compat *wordptr = &wordlist[TOTAL_KEYWORDS + lookup[offset]];
- register const struct id3_compat *wordendptr = wordptr + -lookup[offset + 1];
-
- while (wordptr < wordendptr)
- {
- register const char *s = wordptr->id;
-
- if (*str == *s && !strncmp (str + 1, s + 1, len - 1))
- return wordptr;
- wordptr++;
- }
- }
- }
- }
- return 0;
-}
-
-static
-int translate_TCON(struct id3_frame *frame, char const *oldid,
- id3_byte_t const *data, id3_length_t length)
-{
- id3_byte_t const *end;
- enum id3_field_textencoding encoding;
- id3_ucs4_t *string = 0, *ptr, *endptr;
- int result = 0;
-
- /* translate old TCON syntax into multiple strings */
-
- assert(frame->nfields == 2);
-
- encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1;
-
- end = data + length;
-
- if (id3_field_parse(&frame->fields[0], &data, end - data, &encoding) == -1)
- goto fail;
-
- string = id3_parse_string(&data, end - data, encoding, 0);
- if (string == 0)
- goto fail;
-
- ptr = string;
- while (*ptr == '(') {
- if (*++ptr == '(')
- break;
-
- endptr = ptr;
- while (*endptr && *endptr != ')')
- ++endptr;
-
- if (*endptr)
- *endptr++ = 0;
-
- if (id3_field_addstring(&frame->fields[1], ptr) == -1)
- goto fail;
-
- ptr = endptr;
- }
-
- if (*ptr && id3_field_addstring(&frame->fields[1], ptr) == -1)
- goto fail;
-
- if (0) {
- fail:
- result = -1;
- }
-
- if (string)
- free(string);
-
- return result;
-}
-
-/*
- * NAME: compat->fixup()
- * DESCRIPTION: finish compatibility translations
- */
-int id3_compat_fixup(struct id3_tag *tag)
-{
- struct id3_frame *frame;
- unsigned int index;
- id3_ucs4_t timestamp[17] = { 0 };
- int result = 0;
-
- /* create a TDRC frame from obsolete TYER/TDAT/TIME frames */
-
- /*
- * TYE/TYER: YYYY
- * TDA/TDAT: DDMM
- * TIM/TIME: HHMM
- *
- * TDRC: yyyy-MM-ddTHH:mm
- */
-
- index = 0;
- while ((frame = id3_tag_findframe(tag, ID3_FRAME_OBSOLETE, index++))) {
- char const *id;
- id3_byte_t const *data, *end;
- id3_length_t length;
- enum id3_field_textencoding encoding;
- id3_ucs4_t *string;
-
- id = id3_field_getframeid(&frame->fields[0]);
- assert(id);
-
- if (strcmp(id, "TYER") != 0 && strcmp(id, "YTYE") != 0 &&
- strcmp(id, "TDAT") != 0 && strcmp(id, "YTDA") != 0 &&
- strcmp(id, "TIME") != 0 && strcmp(id, "YTIM") != 0)
- continue;
-
- data = id3_field_getbinarydata(&frame->fields[1], &length);
- assert(data);
-
- if (length < 1)
- continue;
-
- end = data + length;
-
- encoding = id3_parse_uint(&data, 1);
- string = id3_parse_string(&data, end - data, encoding, 0);
-
- if (string == 0)
- continue;
-
- if (id3_ucs4_length(string) < 4) {
- free(string);
- continue;
- }
-
- if (strcmp(id, "TYER") == 0 ||
- strcmp(id, "YTYE") == 0) {
- timestamp[0] = string[0];
- timestamp[1] = string[1];
- timestamp[2] = string[2];
- timestamp[3] = string[3];
- }
- else if (strcmp(id, "TDAT") == 0 ||
- strcmp(id, "YTDA") == 0) {
- timestamp[4] = '-';
- timestamp[5] = string[2];
- timestamp[6] = string[3];
- timestamp[7] = '-';
- timestamp[8] = string[0];
- timestamp[9] = string[1];
- }
- else { /* TIME or YTIM */
- timestamp[10] = 'T';
- timestamp[11] = string[0];
- timestamp[12] = string[1];
- timestamp[13] = ':';
- timestamp[14] = string[2];
- timestamp[15] = string[3];
- }
-
- free(string);
- }
-
- if (timestamp[0]) {
- id3_ucs4_t *strings;
-
- frame = id3_frame_new("TDRC");
- if (frame == 0)
- goto fail;
-
- strings = timestamp;
-
- if (id3_field_settextencoding(&frame->fields[0],
- ID3_FIELD_TEXTENCODING_ISO_8859_1) == -1 ||
- id3_field_setstrings(&frame->fields[1], 1, &strings) == -1 ||
- id3_tag_attachframe(tag, frame) == -1) {
- id3_frame_delete(frame);
- goto fail;
- }
- }
-
- if (0) {
- fail:
- result = -1;
- }
-
- return result;
-}
diff --git a/src/libid3tag/compat.gperf b/src/libid3tag/compat.gperf
deleted file mode 100644
index 8d33868..0000000
--- a/src/libid3tag/compat.gperf
+++ /dev/null
@@ -1,300 +0,0 @@
-%{
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: compat.gperf,v 1.11 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <stdlib.h>
-# include <string.h>
-
-# ifdef HAVE_ASSERT_H
-# include <assert.h>
-# endif
-
-# include "id3tag.h"
-# include "compat.h"
-# include "frame.h"
-# include "field.h"
-# include "parse.h"
-# include "ucs4.h"
-
-# define EQ(id) #id, 0
-# define OBSOLETE 0, 0
-# define TX(id) #id, translate_##id
-
-static id3_compat_func_t translate_TCON;
-%}
-struct id3_compat;
-%%
-#
-# ID3v2.2 and ID3v2.3 frames
-#
-# Only obsolete frames or frames with an equivalent ID3v2.4 frame ID are
-# listed here. If a frame ID is not listed, it is assumed that the same
-# frame ID is itself the equivalent ID3v2.4 frame ID.
-#
-# This list may also include frames with new content interpretations; the
-# translation function will rewrite the contents to comply with ID3v2.4.
-#
-BUF, EQ(RBUF) /* Recommended buffer size */
-CNT, EQ(PCNT) /* Play counter */
-COM, EQ(COMM) /* Comments */
-CRA, EQ(AENC) /* Audio encryption */
-CRM, OBSOLETE /* Encrypted meta frame [obsolete] */
-EQU, OBSOLETE /* Equalization [obsolete] */
-EQUA, OBSOLETE /* Equalization [obsolete] */
-ETC, EQ(ETCO) /* Event timing codes */
-GEO, EQ(GEOB) /* General encapsulated object */
-IPL, EQ(TIPL) /* Involved people list */
-IPLS, EQ(TIPL) /* Involved people list */
-LNK, EQ(LINK) /* Linked information */
-MCI, EQ(MCDI) /* Music CD identifier */
-MLL, EQ(MLLT) /* MPEG location lookup table */
-PIC, EQ(APIC) /* Attached picture */
-POP, EQ(POPM) /* Popularimeter */
-REV, EQ(RVRB) /* Reverb */
-RVA, OBSOLETE /* Relative volume adjustment [obsolete] */
-RVAD, OBSOLETE /* Relative volume adjustment [obsolete] */
-SLT, EQ(SYLT) /* Synchronised lyric/text */
-STC, EQ(SYTC) /* Synchronised tempo codes */
-TAL, EQ(TALB) /* Album/movie/show title */
-TBP, EQ(TBPM) /* BPM (beats per minute) */
-TCM, EQ(TCOM) /* Composer */
-TCO, TX(TCON) /* Content type */
-TCON, TX(TCON) /* Content type */
-TCR, EQ(TCOP) /* Copyright message */
-TDA, OBSOLETE /* Date [obsolete] */
-TDAT, OBSOLETE /* Date [obsolete] */
-TDY, EQ(TDLY) /* Playlist delay */
-TEN, EQ(TENC) /* Encoded by */
-TFT, EQ(TFLT) /* File type */
-TIM, OBSOLETE /* Time [obsolete] */
-TIME, OBSOLETE /* Time [obsolete] */
-TKE, EQ(TKEY) /* Initial key */
-TLA, EQ(TLAN) /* Language(s) */
-TLE, EQ(TLEN) /* Length */
-TMT, EQ(TMED) /* Media type */
-TOA, EQ(TOPE) /* Original artist(s)/performer(s) */
-TOF, EQ(TOFN) /* Original filename */
-TOL, EQ(TOLY) /* Original lyricist(s)/text writer(s) */
-TOR, EQ(TDOR) /* Original release year [obsolete] */
-TORY, EQ(TDOR) /* Original release year [obsolete] */
-TOT, EQ(TOAL) /* Original album/movie/show title */
-TP1, EQ(TPE1) /* Lead performer(s)/soloist(s) */
-TP2, EQ(TPE2) /* Band/orchestra/accompaniment */
-TP3, EQ(TPE3) /* Conductor/performer refinement */
-TP4, EQ(TPE4) /* Interpreted, remixed, or otherwise modified by */
-TPA, EQ(TPOS) /* Part of a set */
-TPB, EQ(TPUB) /* Publisher */
-TRC, EQ(TSRC) /* ISRC (international standard recording code) */
-TRD, OBSOLETE /* Recording dates [obsolete] */
-TRDA, OBSOLETE /* Recording dates [obsolete] */
-TRK, EQ(TRCK) /* Track number/position in set */
-TSI, OBSOLETE /* Size [obsolete] */
-TSIZ, OBSOLETE /* Size [obsolete] */
-TSS, EQ(TSSE) /* Software/hardware and settings used for encoding */
-TT1, EQ(TIT1) /* Content group description */
-TT2, EQ(TIT2) /* Title/songname/content description */
-TT3, EQ(TIT3) /* Subtitle/description refinement */
-TXT, EQ(TEXT) /* Lyricist/text writer */
-TXX, EQ(TXXX) /* User defined text information frame */
-TYE, OBSOLETE /* Year [obsolete] */
-TYER, OBSOLETE /* Year [obsolete] */
-UFI, EQ(UFID) /* Unique file identifier */
-ULT, EQ(USLT) /* Unsynchronised lyric/text transcription */
-WAF, EQ(WOAF) /* Official audio file webpage */
-WAR, EQ(WOAR) /* Official artist/performer webpage */
-WAS, EQ(WOAS) /* Official audio source webpage */
-WCM, EQ(WCOM) /* Commercial information */
-WCP, EQ(WCOP) /* Copyright/legal information */
-WPB, EQ(WPUB) /* Publishers official webpage */
-WXX, EQ(WXXX) /* User defined URL link frame */
-%%
-
-static
-int translate_TCON(struct id3_frame *frame, char const *oldid,
- id3_byte_t const *data, id3_length_t length)
-{
- id3_byte_t const *end;
- enum id3_field_textencoding encoding;
- id3_ucs4_t *string = 0, *ptr, *endptr;
- int result = 0;
-
- /* translate old TCON syntax into multiple strings */
-
- assert(frame->nfields == 2);
-
- encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1;
-
- end = data + length;
-
- if (id3_field_parse(&frame->fields[0], &data, end - data, &encoding) == -1)
- goto fail;
-
- string = id3_parse_string(&data, end - data, encoding, 0);
- if (string == 0)
- goto fail;
-
- ptr = string;
- while (*ptr == '(') {
- if (*++ptr == '(')
- break;
-
- endptr = ptr;
- while (*endptr && *endptr != ')')
- ++endptr;
-
- if (*endptr)
- *endptr++ = 0;
-
- if (id3_field_addstring(&frame->fields[1], ptr) == -1)
- goto fail;
-
- ptr = endptr;
- }
-
- if (*ptr && id3_field_addstring(&frame->fields[1], ptr) == -1)
- goto fail;
-
- if (0) {
- fail:
- result = -1;
- }
-
- if (string)
- free(string);
-
- return result;
-}
-
-/*
- * NAME: compat->fixup()
- * DESCRIPTION: finish compatibility translations
- */
-int id3_compat_fixup(struct id3_tag *tag)
-{
- struct id3_frame *frame;
- unsigned int index;
- id3_ucs4_t timestamp[17] = { 0 };
- int result = 0;
-
- /* create a TDRC frame from obsolete TYER/TDAT/TIME frames */
-
- /*
- * TYE/TYER: YYYY
- * TDA/TDAT: DDMM
- * TIM/TIME: HHMM
- *
- * TDRC: yyyy-MM-ddTHH:mm
- */
-
- index = 0;
- while ((frame = id3_tag_findframe(tag, ID3_FRAME_OBSOLETE, index++))) {
- char const *id;
- id3_byte_t const *data, *end;
- id3_length_t length;
- enum id3_field_textencoding encoding;
- id3_ucs4_t *string;
-
- id = id3_field_getframeid(&frame->fields[0]);
- assert(id);
-
- if (strcmp(id, "TYER") != 0 && strcmp(id, "YTYE") != 0 &&
- strcmp(id, "TDAT") != 0 && strcmp(id, "YTDA") != 0 &&
- strcmp(id, "TIME") != 0 && strcmp(id, "YTIM") != 0)
- continue;
-
- data = id3_field_getbinarydata(&frame->fields[1], &length);
- assert(data);
-
- if (length < 1)
- continue;
-
- end = data + length;
-
- encoding = id3_parse_uint(&data, 1);
- string = id3_parse_string(&data, end - data, encoding, 0);
-
- if (string == 0)
- continue;
-
- if (id3_ucs4_length(string) < 4) {
- free(string);
- continue;
- }
-
- if (strcmp(id, "TYER") == 0 ||
- strcmp(id, "YTYE") == 0) {
- timestamp[0] = string[0];
- timestamp[1] = string[1];
- timestamp[2] = string[2];
- timestamp[3] = string[3];
- }
- else if (strcmp(id, "TDAT") == 0 ||
- strcmp(id, "YTDA") == 0) {
- timestamp[4] = '-';
- timestamp[5] = string[2];
- timestamp[6] = string[3];
- timestamp[7] = '-';
- timestamp[8] = string[0];
- timestamp[9] = string[1];
- }
- else { /* TIME or YTIM */
- timestamp[10] = 'T';
- timestamp[11] = string[0];
- timestamp[12] = string[1];
- timestamp[13] = ':';
- timestamp[14] = string[2];
- timestamp[15] = string[3];
- }
-
- free(string);
- }
-
- if (timestamp[0]) {
- id3_ucs4_t *strings;
-
- frame = id3_frame_new("TDRC");
- if (frame == 0)
- goto fail;
-
- strings = timestamp;
-
- if (id3_field_settextencoding(&frame->fields[0],
- ID3_FIELD_TEXTENCODING_ISO_8859_1) == -1 ||
- id3_field_setstrings(&frame->fields[1], 1, &strings) == -1 ||
- id3_tag_attachframe(tag, frame) == -1) {
- id3_frame_delete(frame);
- goto fail;
- }
- }
-
- if (0) {
- fail:
- result = -1;
- }
-
- return result;
-}
diff --git a/src/libid3tag/compat.h b/src/libid3tag/compat.h
deleted file mode 100644
index 8af71ec..0000000
--- a/src/libid3tag/compat.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: compat.h,v 1.8 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_COMPAT_H
-# define LIBID3TAG_COMPAT_H
-
-# include "id3tag.h"
-
-typedef int id3_compat_func_t(struct id3_frame *, char const *,
- id3_byte_t const *, id3_length_t);
-
-struct id3_compat {
- char const *id;
- char const *equiv;
- id3_compat_func_t *translate;
-};
-
-struct id3_compat const *id3_compat_lookup(register char const *,
- register unsigned int);
-
-int id3_compat_fixup(struct id3_tag *);
-
-# endif
diff --git a/src/libid3tag/config.h b/src/libid3tag/config.h
deleted file mode 100644
index 769f2e6..0000000
--- a/src/libid3tag/config.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* config.h. Generated by configure. */
-/* config.h.in. Generated from configure.ac by autoheader. */
-
-/* Define to enable diagnostic debugging support. */
-/* #undef DEBUG */
-
-/* Define to 1 if you have the <assert.h> header file. */
-#define HAVE_ASSERT_H 1
-
-/* Define to 1 if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you have the `ftruncate' function. */
-#define HAVE_FTRUNCATE 1
-
-/* Define to 1 if you have the <inttypes.h> header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the `z' library (-lz). */
-#define HAVE_LIBZ 1
-
-/* Define to 1 if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the <stdint.h> header file. */
-#define HAVE_STDINT_H 1
-
-/* Define to 1 if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define to 1 if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define to 1 if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define to 1 if you have the <sys/stat.h> header file. */
-#define HAVE_SYS_STAT_H 1
-
-/* Define to 1 if you have the <sys/types.h> header file. */
-#define HAVE_SYS_TYPES_H 1
-
-/* Define to 1 if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to disable debugging assertions. */
-/* #undef NDEBUG */
-
-/* Name of package */
-#define PACKAGE "libid3tag"
-
-/* Define to the address where bug reports for this package should be sent. */
-#define PACKAGE_BUGREPORT "support@underbit.com"
-
-/* Define to the full name of this package. */
-#define PACKAGE_NAME "ID3 Tag"
-
-/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "ID3 Tag 0.15.1b"
-
-/* Define to the one symbol short name of this package. */
-#define PACKAGE_TARNAME "libid3tag"
-
-/* Define to the version of this package. */
-#define PACKAGE_VERSION "0.15.1b"
-
-/* Define to 1 if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Version number of package */
-#define VERSION "0.15.1b"
-
-/* Define to empty if `const' does not conform to ANSI C. */
-/* #undef const */
-
-/* Define to `__inline__' or `__inline' if that's what the C compiler
- calls it, or to nothing if 'inline' is not supported under any name. */
-#ifndef __cplusplus
-/* #undef inline */
-#endif
diff --git a/src/libid3tag/crc.c b/src/libid3tag/crc.c
deleted file mode 100644
index 742a5d8..0000000
--- a/src/libid3tag/crc.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: crc.c,v 1.11 2004/02/17 02:04:10 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include "id3tag.h"
-# include "crc.h"
-
-static
-unsigned long const crc_table[256] = {
- 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL,
- 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
- 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L,
- 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
- 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
- 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
- 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL,
- 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
-
- 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L,
- 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
- 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L,
- 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
- 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L,
- 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
- 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
- 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
-
- 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL,
- 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
- 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L,
- 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
- 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL,
- 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
- 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL,
- 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
-
- 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
- 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
- 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L,
- 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
- 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L,
- 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
- 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L,
- 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
-
- 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL,
- 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
- 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
- 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
- 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL,
- 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
- 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL,
- 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
-
- 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L,
- 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
- 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L,
- 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
- 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
- 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
- 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L,
- 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
-
- 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL,
- 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
- 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L,
- 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
- 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL,
- 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
- 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
- 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
-
- 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L,
- 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
- 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L,
- 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
- 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L,
- 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
- 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L,
- 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
-};
-
-/*
- * NAME: crc->compute()
- * DESCRIPTION: calculate CRC-32 value (ISO 3309)
- */
-unsigned long id3_crc_compute(id3_byte_t const *data, id3_length_t length)
-{
- register unsigned long crc;
-
- for (crc = 0xffffffffL; length >= 8; length -= 8) {
- crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- }
-
- switch (length) {
- case 7: crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- case 6: crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- case 5: crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- case 4: crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- case 3: crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- case 2: crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- case 1: crc = crc_table[(crc ^ *data++) & 0xff] ^ (crc >> 8);
- case 0: break;
- }
-
- return crc ^ 0xffffffffL;
-}
diff --git a/src/libid3tag/crc.h b/src/libid3tag/crc.h
deleted file mode 100644
index 89a5a39..0000000
--- a/src/libid3tag/crc.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: crc.h,v 1.8 2004/02/17 02:04:10 rob Exp $
- */
-
-# ifndef LIBID3TAG_CRC_H
-# define LIBID3TAG_CRC_H
-
-# include "id3tag.h"
-
-unsigned long id3_crc_compute(id3_byte_t const *, id3_length_t);
-
-# endif
diff --git a/src/libid3tag/debug.c b/src/libid3tag/debug.c
deleted file mode 100644
index d91a2c5..0000000
--- a/src/libid3tag/debug.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: debug.c,v 1.8 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# undef malloc
-# undef calloc
-# undef realloc
-# undef free
-
-# include <stdio.h>
-# include <stdlib.h>
-# include <string.h>
-
-# include "debug.h"
-
-# if defined(DEBUG)
-
-# define DEBUG_MAGIC 0xdeadbeefL
-
-struct debug {
- char const *file;
- unsigned int line;
- size_t size;
- struct debug *next;
- struct debug *prev;
- long int magic;
-};
-
-static struct debug *allocated;
-static int registered;
-
-static
-void check(void)
-{
- struct debug *debug;
-
- for (debug = allocated; debug; debug = debug->next) {
- if (debug->magic != DEBUG_MAGIC) {
- fprintf(stderr, "memory corruption\n");
- break;
- }
-
- fprintf(stderr, "%s:%u: leaked %lu bytes\n",
- debug->file, debug->line, debug->size);
- }
-}
-
-void *id3_debug_malloc(size_t size, char const *file, unsigned int line)
-{
- struct debug *debug;
-
- if (!registered) {
- atexit(check);
- registered = 1;
- }
-
- if (size == 0)
- fprintf(stderr, "%s:%u: malloc(0)\n", file, line);
-
- debug = malloc(sizeof(*debug) + size);
- if (debug == 0) {
- fprintf(stderr, "%s:%u: malloc(%lu) failed\n", file, line, size);
- return 0;
- }
-
- debug->magic = DEBUG_MAGIC;
-
- debug->file = file;
- debug->line = line;
- debug->size = size;
-
- debug->next = allocated;
- debug->prev = 0;
-
- if (allocated)
- allocated->prev = debug;
-
- allocated = debug;
-
- return ++debug;
-}
-
-void *id3_debug_calloc(size_t nmemb, size_t size,
- char const *file, unsigned int line)
-{
- void *ptr;
-
- ptr = id3_debug_malloc(nmemb * size, file, line);
- if (ptr)
- memset(ptr, 0, nmemb * size);
-
- return ptr;
-}
-
-void *id3_debug_realloc(void *ptr, size_t size,
- char const *file, unsigned int line)
-{
- struct debug *debug, *new;
-
- if (size == 0) {
- id3_debug_free(ptr, file, line);
- return 0;
- }
-
- if (ptr == 0)
- return id3_debug_malloc(size, file, line);
-
- debug = ptr;
- --debug;
-
- if (debug->magic != DEBUG_MAGIC) {
- fprintf(stderr, "%s:%u: realloc(%p, %lu) memory not allocated\n",
- file, line, ptr, size);
- return 0;
- }
-
- new = realloc(debug, sizeof(*debug) + size);
- if (new == 0) {
- fprintf(stderr, "%s:%u: realloc(%p, %lu) failed\n", file, line, ptr, size);
- return 0;
- }
-
- if (allocated == debug)
- allocated = new;
-
- debug = new;
-
- debug->file = file;
- debug->line = line;
- debug->size = size;
-
- if (debug->next)
- debug->next->prev = debug;
- if (debug->prev)
- debug->prev->next = debug;
-
- return ++debug;
-}
-
-void id3_debug_free(void *ptr, char const *file, unsigned int line)
-{
- struct debug *debug;
-
- if (ptr == 0) {
- fprintf(stderr, "%s:%u: free(0)\n", file, line);
- return;
- }
-
- debug = ptr;
- --debug;
-
- if (debug->magic != DEBUG_MAGIC) {
- fprintf(stderr, "%s:%u: free(%p) memory not allocated\n", file, line, ptr);
- return;
- }
-
- debug->magic = 0;
-
- if (debug->next)
- debug->next->prev = debug->prev;
- if (debug->prev)
- debug->prev->next = debug->next;
-
- if (allocated == debug)
- allocated = debug->next;
-
- free(debug);
-}
-
-void *id3_debug_release(void *ptr, char const *file, unsigned int line)
-{
- struct debug *debug;
-
- if (ptr == 0)
- return 0;
-
- debug = ptr;
- --debug;
-
- if (debug->magic != DEBUG_MAGIC) {
- fprintf(stderr, "%s:%u: release(%p) memory not allocated\n",
- file, line, ptr);
- return ptr;
- }
-
- if (debug->next)
- debug->next->prev = debug->prev;
- if (debug->prev)
- debug->prev->next = debug->next;
-
- if (allocated == debug)
- allocated = debug->next;
-
- memmove(debug, debug + 1, debug->size);
-
- return debug;
-}
-
-# endif
diff --git a/src/libid3tag/debug.h b/src/libid3tag/debug.h
deleted file mode 100644
index a9b4ce0..0000000
--- a/src/libid3tag/debug.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: debug.h,v 1.8 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_DEBUG_H
-# define LIBID3TAG_DEBUG_H
-
-# include <stdlib.h>
-
-void *id3_debug_malloc(size_t, char const *, unsigned int);
-void *id3_debug_calloc(size_t, size_t, char const *, unsigned int);
-void *id3_debug_realloc(void *, size_t, char const *, unsigned int);
-void id3_debug_free(void *, char const *, unsigned int);
-
-void *id3_debug_release(void *, char const *, unsigned int);
-
-# endif
diff --git a/src/libid3tag/field.c b/src/libid3tag/field.c
deleted file mode 100644
index 6698b86..0000000
--- a/src/libid3tag/field.c
+++ /dev/null
@@ -1,906 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: field.c,v 1.16 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <stdlib.h>
-# include <stdio.h>
-# include <string.h>
-
-# ifdef HAVE_ASSERT_H
-# include <assert.h>
-# endif
-
-# include "id3tag.h"
-# include "field.h"
-# include "frame.h"
-# include "render.h"
-# include "ucs4.h"
-# include "latin1.h"
-# include "parse.h"
-
-/*
- * NAME: field->init()
- * DESCRIPTION: initialize a field to a default value for the given type
- */
-void id3_field_init(union id3_field *field, enum id3_field_type type)
-{
- assert(field);
-
- switch (field->type = type) {
- case ID3_FIELD_TYPE_TEXTENCODING:
- case ID3_FIELD_TYPE_INT8:
- case ID3_FIELD_TYPE_INT16:
- case ID3_FIELD_TYPE_INT24:
- case ID3_FIELD_TYPE_INT32:
- field->number.value = 0;
- break;
-
- case ID3_FIELD_TYPE_LATIN1:
- case ID3_FIELD_TYPE_LATIN1FULL:
- field->latin1.ptr = 0;
- break;
-
- case ID3_FIELD_TYPE_LATIN1LIST:
- field->latin1list.nstrings = 0;
- field->latin1list.strings = 0;
-
- case ID3_FIELD_TYPE_STRING:
- case ID3_FIELD_TYPE_STRINGFULL:
- field->string.ptr = 0;
- break;
-
- case ID3_FIELD_TYPE_STRINGLIST:
- field->stringlist.nstrings = 0;
- field->stringlist.strings = 0;
- break;
-
- case ID3_FIELD_TYPE_LANGUAGE:
- g_strlcpy(field->immediate.value, "XXX", sizeof(field->immediate.value));
- break;
-
- case ID3_FIELD_TYPE_FRAMEID:
- g_strlcpy(field->immediate.value, "XXXX", sizeof(field->immediate.value));
- break;
-
- case ID3_FIELD_TYPE_DATE:
- memset(field->immediate.value, 0, sizeof(field->immediate.value));
- break;
-
- case ID3_FIELD_TYPE_INT32PLUS:
- case ID3_FIELD_TYPE_BINARYDATA:
- field->binary.data = 0;
- field->binary.length = 0;
- break;
- }
-}
-
-/*
- * NAME: field->finish()
- * DESCRIPTION: reset a field, deallocating memory if necessary
- */
-void id3_field_finish(union id3_field *field)
-{
- unsigned int i;
-
- assert(field);
-
- switch (field->type) {
- case ID3_FIELD_TYPE_TEXTENCODING:
- case ID3_FIELD_TYPE_INT8:
- case ID3_FIELD_TYPE_INT16:
- case ID3_FIELD_TYPE_INT24:
- case ID3_FIELD_TYPE_INT32:
- case ID3_FIELD_TYPE_LANGUAGE:
- case ID3_FIELD_TYPE_FRAMEID:
- case ID3_FIELD_TYPE_DATE:
- break;
-
- case ID3_FIELD_TYPE_LATIN1:
- case ID3_FIELD_TYPE_LATIN1FULL:
- if (field->latin1.ptr) {
- free(field->latin1.ptr);
- field->latin1.ptr = NULL;
- }
- break;
-
- case ID3_FIELD_TYPE_LATIN1LIST:
- if (field->latin1list.strings) {
- for (i = 0; i < field->latin1list.nstrings; ++i)
- free(field->latin1list.strings[i]);
-
- free(field->latin1list.strings);
- field->latin1list.nstrings = 0;
- field->latin1list.strings = NULL;
- }
- break;
-
- case ID3_FIELD_TYPE_STRING:
- case ID3_FIELD_TYPE_STRINGFULL:
- if (field->string.ptr) {
- free(field->string.ptr);
- field->string.ptr = NULL;
- }
- break;
-
- case ID3_FIELD_TYPE_STRINGLIST:
- if (field->stringlist.strings) {
- for (i = 0; i < field->stringlist.nstrings; ++i)
- free(field->stringlist.strings[i]);
-
- free(field->stringlist.strings);
- field->stringlist.nstrings = 0;
- field->stringlist.strings = NULL;
- }
- break;
-
- case ID3_FIELD_TYPE_INT32PLUS:
- case ID3_FIELD_TYPE_BINARYDATA:
- if (field->binary.data) {
- free(field->binary.data);
- field->binary.data = NULL;
- }
- break;
- }
-
- id3_field_init(field, field->type);
-}
-
-/*
- * NAME: field->type()
- * DESCRIPTION: return the value type of a field
- */
-enum id3_field_type id3_field_type(union id3_field const *field)
-{
- assert(field);
-
- return field->type;
-}
-
-/*
- * NAME: field->parse()
- * DESCRIPTION: parse a field value
- */
-int id3_field_parse(union id3_field *field, id3_byte_t const **ptr,
- id3_length_t length, enum id3_field_textencoding *encoding)
-{
- assert(field);
-
- id3_field_finish(field);
-
- switch (field->type) {
- case ID3_FIELD_TYPE_INT32:
- if (length < 4)
- goto fail;
-
- field->number.value = id3_parse_uint(ptr, 4);
- break;
-
- case ID3_FIELD_TYPE_INT24:
- if (length < 3)
- goto fail;
-
- field->number.value = id3_parse_uint(ptr, 3);
- break;
-
- case ID3_FIELD_TYPE_INT16:
- if (length < 2)
- goto fail;
-
- field->number.value = id3_parse_uint(ptr, 2);
- break;
-
- case ID3_FIELD_TYPE_INT8:
- case ID3_FIELD_TYPE_TEXTENCODING:
- if (length < 1)
- goto fail;
-
- field->number.value = id3_parse_uint(ptr, 1);
-
- if (field->type == ID3_FIELD_TYPE_TEXTENCODING)
- *encoding = field->number.value;
- break;
-
- case ID3_FIELD_TYPE_LANGUAGE:
- if (length < 3)
- goto fail;
-
- id3_parse_immediate(ptr, 3, field->immediate.value);
- break;
-
- case ID3_FIELD_TYPE_FRAMEID:
- if (length < 4)
- goto fail;
-
- id3_parse_immediate(ptr, 4, field->immediate.value);
- break;
-
- case ID3_FIELD_TYPE_DATE:
- if (length < 8)
- goto fail;
-
- id3_parse_immediate(ptr, 8, field->immediate.value);
- break;
-
- case ID3_FIELD_TYPE_LATIN1:
- case ID3_FIELD_TYPE_LATIN1FULL:
- {
- id3_latin1_t *latin1;
-
- latin1 = id3_parse_latin1(ptr, length,
- field->type == ID3_FIELD_TYPE_LATIN1FULL);
- if (latin1 == 0)
- goto fail;
-
- field->latin1.ptr = latin1;
- }
- break;
-
- case ID3_FIELD_TYPE_LATIN1LIST:
- {
- id3_byte_t const *end;
- id3_latin1_t *latin1, **strings;
-
- end = *ptr + length;
-
- while (end - *ptr > 0 && **ptr != '\0') {
- latin1 = id3_parse_latin1(ptr, end - *ptr, 0);
- if (latin1 == 0)
- goto fail;
-
- strings = realloc(field->latin1list.strings,
- (field->latin1list.nstrings + 1) * sizeof(*strings));
- if (strings == 0) {
- free(latin1);
- goto fail;
- }
-
- field->latin1list.strings = strings;
- field->latin1list.strings[field->latin1list.nstrings++] = latin1;
- }
- }
- break;
-
- case ID3_FIELD_TYPE_STRING:
- case ID3_FIELD_TYPE_STRINGFULL:
- {
- id3_ucs4_t *ucs4;
-
- ucs4 = id3_parse_string(ptr, length, *encoding,
- field->type == ID3_FIELD_TYPE_STRINGFULL);
- if (ucs4 == 0)
- goto fail;
-
- field->string.ptr = ucs4;
- }
- break;
-
- case ID3_FIELD_TYPE_STRINGLIST:
- {
- id3_byte_t const *end;
- id3_ucs4_t *ucs4, **strings;
-
- end = *ptr + length;
-
- while (end - *ptr > 0 && **ptr != '\0') {
- ucs4 = id3_parse_string(ptr, end - *ptr, *encoding, 0);
- if (ucs4 == 0)
- goto fail;
-
- strings = realloc(field->stringlist.strings,
- (field->stringlist.nstrings + 1) * sizeof(*strings));
- if (strings == 0) {
- free(ucs4);
- goto fail;
- }
-
- field->stringlist.strings = strings;
- field->stringlist.strings[field->stringlist.nstrings++] = ucs4;
- }
- }
- break;
-
- case ID3_FIELD_TYPE_INT32PLUS:
- case ID3_FIELD_TYPE_BINARYDATA:
- {
- id3_byte_t *data;
-
- data = id3_parse_binary(ptr, length);
- if (data == 0)
- goto fail;
-
- field->binary.data = data;
- field->binary.length = length;
- }
- break;
- }
-
- return 0;
-
- fail:
- return -1;
-}
-
-/*
- * NAME: field->render()
- * DESCRIPTION: render a field value
- */
-id3_length_t id3_field_render(union id3_field const *field, id3_byte_t **ptr,
- enum id3_field_textencoding *encoding,
- int terminate)
-{
- id3_length_t size;
- unsigned int i;
-
- assert(field && encoding);
-
- switch (field->type) {
- case ID3_FIELD_TYPE_INT32:
- return id3_render_int(ptr, field->number.value, 4);
-
- case ID3_FIELD_TYPE_INT24:
- return id3_render_int(ptr, field->number.value, 3);
-
- case ID3_FIELD_TYPE_INT16:
- return id3_render_int(ptr, field->number.value, 2);
-
- case ID3_FIELD_TYPE_TEXTENCODING:
- *encoding = field->number.value;
- case ID3_FIELD_TYPE_INT8:
- return id3_render_int(ptr, field->number.value, 1);
-
- case ID3_FIELD_TYPE_LATIN1:
- case ID3_FIELD_TYPE_LATIN1FULL:
- return id3_render_latin1(ptr, field->latin1.ptr, terminate);
-
- case ID3_FIELD_TYPE_LATIN1LIST:
- size = 0;
- for (i = 0; i < field->latin1list.nstrings; ++i) {
- size += id3_render_latin1(ptr, field->latin1list.strings[i],
- (i < field->latin1list.nstrings - 1) ||
- terminate);
- }
- return size;
-
- case ID3_FIELD_TYPE_STRING:
- case ID3_FIELD_TYPE_STRINGFULL: // here !! --yaz
- return id3_render_string(ptr, field->string.ptr, *encoding, terminate);
-
- case ID3_FIELD_TYPE_STRINGLIST:
- size = 0;
- for (i = 0; i < field->stringlist.nstrings; ++i) {
- size += id3_render_string(ptr, field->stringlist.strings[i], *encoding,
- (i < field->stringlist.nstrings - 1) ||
- terminate);
- }
- return size;
-
- case ID3_FIELD_TYPE_LANGUAGE:
- return id3_render_immediate(ptr, field->immediate.value, 3);
-
- case ID3_FIELD_TYPE_FRAMEID:
- return id3_render_immediate(ptr, field->immediate.value, 4);
-
- case ID3_FIELD_TYPE_DATE:
- return id3_render_immediate(ptr, field->immediate.value, 8);
-
- case ID3_FIELD_TYPE_INT32PLUS:
- case ID3_FIELD_TYPE_BINARYDATA:
- return id3_render_binary(ptr, field->binary.data, field->binary.length);
- }
-
- return 0;
-}
-
-/*
- * NAME: field->setint()
- * DESCRIPTION: set the value of an int field
- */
-int id3_field_setint(union id3_field *field, signed long number)
-{
- assert(field);
-
- switch (field->type) {
- case ID3_FIELD_TYPE_INT8:
- if (number > 0x7f || number < -0x80)
- return -1;
- break;
-
- case ID3_FIELD_TYPE_INT16:
- if (number > 0x7fff || number < -0x8000)
- return -1;
- break;
-
- case ID3_FIELD_TYPE_INT24:
- if (number > 0x7fffffL || number < -0x800000L)
- return -1;
- break;
-
- case ID3_FIELD_TYPE_INT32:
- if (number > 0x7fffffffL || number < -0x80000000L)
- return -1;
- break;
-
- default:
- return -1;
- }
-
- id3_field_finish(field);
-
- field->number.value = number;
-
- return 0;
-}
-
-/*
- * NAME: field->settextencoding()
- * DESCRIPTION: set the value of a textencoding field
- */
-int id3_field_settextencoding(union id3_field *field,
- enum id3_field_textencoding encoding)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_TEXTENCODING) {
- return -1;
- }
-
- id3_field_finish(field);
-
- field->number.value = encoding;
-
- return 0;
-}
-
-static
-int set_latin1(union id3_field *field, id3_latin1_t const *latin1)
-{
- id3_latin1_t *data;
-
- if (latin1 == 0 || *latin1 == 0)
- data = 0;
- else {
- data = id3_latin1_duplicate(latin1);
- if (data == 0)
- return -1;
- }
-
- field->latin1.ptr = data;
-
- return 0;
-}
-
-/*
- * NAME: field->setlatin1()
- * DESCRIPTION: set the value of a latin1 field
- */
-int id3_field_setlatin1(union id3_field *field, id3_latin1_t const *latin1)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_LATIN1)
- return -1;
-
- id3_field_finish(field);
-
- if (latin1) {
- id3_latin1_t const *ptr;
-
- for (ptr = latin1; *ptr; ++ptr) {
- if (*ptr == '\n')
- return -1;
- }
- }
-
- return set_latin1(field, latin1);
-}
-
-/*
- * NAME: field->setfulllatin1()
- * DESCRIPTION: set the value of a full latin1 field
- */
-int id3_field_setfulllatin1(union id3_field *field, id3_latin1_t const *latin1)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_LATIN1FULL)
- return -1;
-
- id3_field_finish(field);
-
- return set_latin1(field, latin1);
-}
-
-static
-int set_string(union id3_field *field, id3_ucs4_t const *string)
-{
- id3_ucs4_t *data;
-
- if (string == 0 || *string == 0)
- data = 0;
- else {
- data = id3_ucs4_duplicate(string);
- if (data == 0)
- return -1;
- }
-
- field->string.ptr = data;
-
- return 0;
-}
-
-/*
- * NAME: field->setstring()
- * DESCRIPTION: set the value of a string field
- */
-int id3_field_setstring(union id3_field *field, id3_ucs4_t const *string)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_STRING)
- return -1;
-
- id3_field_finish(field);
-
- if (string) {
- id3_ucs4_t const *ptr;
-
- for (ptr = string; *ptr; ++ptr) {
- if (*ptr == '\n')
- return -1;
- }
- }
-
- return set_string(field, string);
-}
-
-/*
- * NAME: field->setfullstring()
- * DESCRIPTION: set the value of a full string field
- */
-int id3_field_setfullstring(union id3_field *field, id3_ucs4_t const *string)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_STRINGFULL)
- return -1;
-
- id3_field_finish(field);
-
- return set_string(field, string);
-}
-
-/*
- * NAME: field->setstrings()
- * DESCRIPTION: set the value of a stringlist field
- */
-int id3_field_setstrings(union id3_field *field,
- unsigned int length, id3_ucs4_t **ptrs)
-{
- id3_ucs4_t **strings;
- unsigned int i;
-
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_STRINGLIST)
- return -1;
-
- id3_field_finish(field);
-
- if (length == 0)
- return 0;
-
- strings = malloc(length * sizeof(*strings));
- if (strings == 0)
- return -1;
-
- for (i = 0; i < length; ++i) {
- strings[i] = id3_ucs4_duplicate(ptrs[i]);
- if (strings[i] == 0) {
- while (i--)
- free(strings[i]);
-
- free(strings);
- return -1;
- }
- }
-
- field->stringlist.strings = strings;
- field->stringlist.nstrings = length;
-
- return 0;
-}
-
-/*
- * NAME: field->addstring()
- * DESCRIPTION: add a string to a stringlist field
- */
-int id3_field_addstring(union id3_field *field, id3_ucs4_t const *string)
-{
- id3_ucs4_t *new, **strings;
-
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_STRINGLIST)
- return -1;
-
- if (string == 0)
- string = id3_ucs4_empty;
-
- new = id3_ucs4_duplicate(string);
- if (new == 0)
- return -1;
-
- strings = realloc(field->stringlist.strings,
- (field->stringlist.nstrings + 1) * sizeof(*strings));
- if (strings == 0) {
- free(new);
- return -1;
- }
-
- field->stringlist.strings = strings;
- field->stringlist.strings[field->stringlist.nstrings++] = new;
-
- return 0;
-}
-
-/*
- * NAME: field->setlanguage()
- * DESCRIPTION: set the value of a language field
- */
-int id3_field_setlanguage(union id3_field *field, char const *language)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_LANGUAGE)
- return -1;
-
- id3_field_finish(field);
-
- if (language) {
- if (strlen(language) != 3)
- return -1;
-
- g_strlcpy(field->immediate.value, language, sizeof(field->immediate.value));
- }
-
- return 0;
-}
-
-/*
- * NAME: field->setframeid()
- * DESCRIPTION: set the value of a frameid field
- */
-int id3_field_setframeid(union id3_field *field, char const *id)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_FRAMEID ||
- !id3_frame_validid(id))
- return -1;
-
- id3_field_finish(field);
-
- field->immediate.value[0] = id[0];
- field->immediate.value[1] = id[1];
- field->immediate.value[2] = id[2];
- field->immediate.value[3] = id[3];
- field->immediate.value[4] = 0;
-
- return 0;
-}
-
-/*
- * NAME: field->setbinarydata()
- * DESCRIPTION: set the value of a binarydata field
- */
-int id3_field_setbinarydata(union id3_field *field,
- id3_byte_t const *data, id3_length_t length)
-{
- id3_byte_t *mem;
-
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_BINARYDATA)
- return -1;
-
- id3_field_finish(field);
-
- if (length == 0)
- mem = 0;
- else {
- mem = malloc(length);
- if (mem == 0)
- return -1;
-
- assert(data);
-
- memcpy(mem, data, length);
- }
-
- field->binary.data = mem;
- field->binary.length = length;
-
- return 0;
-}
-
-/*
- * NAME: field->getint()
- * DESCRIPTION: return the value of an integer field
- */
-signed long id3_field_getint(union id3_field const *field)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_INT8 &&
- field->type != ID3_FIELD_TYPE_INT16 &&
- field->type != ID3_FIELD_TYPE_INT24 &&
- field->type != ID3_FIELD_TYPE_INT32)
- return -1;
-
- return field->number.value;
-}
-
-/*
- * NAME: field->gettextencoding()
- * DESCRIPTION: return the value of a text encoding field
- */
-enum id3_field_textencoding
-id3_field_gettextencoding(union id3_field const *field)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_TEXTENCODING)
- return -1;
-
- return field->number.value;
-}
-
-/*
- * NAME: field->getlatin1()
- * DESCRIPTION: return the value of a latin1 field
- */
-id3_latin1_t const *id3_field_getlatin1(union id3_field const *field)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_LATIN1)
- return 0;
-
- return field->latin1.ptr ? field->latin1.ptr : (id3_latin1_t const *) "";
-}
-
-/*
- * NAME: field->getfulllatin1()
- * DESCRIPTION: return the value of a full latin1 field
- */
-id3_latin1_t const *id3_field_getfulllatin1(union id3_field const *field)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_LATIN1FULL)
- return 0;
-
- return field->latin1.ptr ? field->latin1.ptr : (id3_latin1_t const *) "";
-}
-
-/*
- * NAME: field->getstring()
- * DESCRIPTION: return the value of a string field
- */
-id3_ucs4_t const *id3_field_getstring(union id3_field const *field)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_STRING)
- return 0;
-
- return field->string.ptr ? field->string.ptr : id3_ucs4_empty;
-}
-
-/*
- * NAME: field->getfullstring()
- * DESCRIPTION: return the value of a fullstring field
- */
-id3_ucs4_t const *id3_field_getfullstring(union id3_field const *field)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_STRINGFULL) {
- printf("not stringfull\n");
- return 0;
- }
-
- return field->string.ptr ? field->string.ptr : id3_ucs4_empty;
-}
-
-/*
- * NAME: field->getnstrings()
- * DESCRIPTION: return the number of strings in a stringlist field
- */
-unsigned int id3_field_getnstrings(union id3_field const *field)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_STRINGLIST)
- return 0;
-
- return field->stringlist.nstrings;
-}
-
-/*
- * NAME: field->getstrings()
- * DESCRIPTION: return one value of a stringlist field
- */
-id3_ucs4_t const *id3_field_getstrings(union id3_field const *field,
- unsigned int index)
-{
- id3_ucs4_t const *string;
-
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_STRINGLIST ||
- index >= field->stringlist.nstrings)
- return 0;
-
- string = field->stringlist.strings[index];
-
- return string ? string : id3_ucs4_empty;
-}
-
-/*
- * NAME: field->getframeid()
- * DESCRIPTION: return the value of a frameid field
- */
-char const *id3_field_getframeid(union id3_field const *field)
-{
- assert(field);
-
- if (field->type != ID3_FIELD_TYPE_FRAMEID)
- return 0;
-
- return field->immediate.value;
-}
-
-/*
- * NAME: field->getbinarydata()
- * DESCRIPTION: return the value of a binarydata field
- */
-id3_byte_t const *id3_field_getbinarydata(union id3_field const *field,
- id3_length_t *length)
-{
- static id3_byte_t const empty;
-
- assert(field && length);
-
- if (field->type != ID3_FIELD_TYPE_BINARYDATA)
- return 0;
-
- assert(field->binary.length == 0 || field->binary.data);
-
- *length = field->binary.length;
-
- return field->binary.data ? field->binary.data : &empty;
-}
diff --git a/src/libid3tag/field.h b/src/libid3tag/field.h
deleted file mode 100644
index 2cf42b9..0000000
--- a/src/libid3tag/field.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: field.h,v 1.9 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_FIELD_H
-# define LIBID3TAG_FIELD_H
-
-# include "id3tag.h"
-
-void id3_field_init(union id3_field *, enum id3_field_type);
-void id3_field_finish(union id3_field *);
-
-int id3_field_parse(union id3_field *, id3_byte_t const **,
- id3_length_t, enum id3_field_textencoding *);
-
-id3_length_t id3_field_render(union id3_field const *, id3_byte_t **,
- enum id3_field_textencoding *, int);
-
-# endif
diff --git a/src/libid3tag/file.c b/src/libid3tag/file.c
deleted file mode 100644
index 082645e..0000000
--- a/src/libid3tag/file.c
+++ /dev/null
@@ -1,843 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: file.c,v 1.21 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <stdio.h>
-# include <stdlib.h>
-# include <string.h>
-
-# ifdef HAVE_UNISTD_H
-# include <unistd.h>
-# endif
-
-# ifdef HAVE_ASSERT_H
-# include <assert.h>
-# endif
-
-# include "id3tag.h"
-# include "file.h"
-# include "tag.h"
-# include "field.h"
-
-#define AUDACIOUS 1
-//#undef AUDACIOUS
-
-#ifdef AUDACIOUS
- #include <libaudcore/vfs.h>
-#else
- #define VFSFile FILE
- #define vfs_fopen fopen
- #define vfs_fclose fclose
- #define vfs_fseek fseek
- #define vfs_ftell ftell
- #define vfs_rewind rewind
- #define vfs_fread fread
- #define vfs_fwrite fwrite
- #define vfs_truncate(x, y) ftruncate((fileno(x)), (y))
-#endif
-
-struct filetag {
- struct id3_tag *tag;
- unsigned long location;
- id3_length_t length;
-};
-
-struct id3_file {
- VFSFile *iofile;
- enum id3_file_mode mode;
- char *path;
-
- int flags;
-
- struct id3_tag *primary;
-
- unsigned int ntags;
- struct filetag *tags;
-};
-
-enum {
- ID3_FILE_FLAG_ID3V1 = 0x0001
-};
-
-/*
- * NAME: query_tag()
- * DESCRIPTION: check for a tag at a file's current position
- */
-static
-signed long query_tag(VFSFile *iofile)
-{
- int save_position;
- id3_byte_t query[ID3_TAG_QUERYSIZE];
- signed long size;
-
- save_position = vfs_ftell(iofile);
- if (save_position == -1)
- return 0;
-
- size = id3_tag_query(query, vfs_fread(query, 1, sizeof(query), iofile));
-
- if(vfs_fseek(iofile, save_position, SEEK_SET) == -1)
- return 0;
-
- return size;
-}
-
-/*
- * NAME: read_tag()
- * DESCRIPTION: read and parse a tag at a file's current position
- */
-static
-struct id3_tag *read_tag(VFSFile *iofile, id3_length_t size)
-{
- id3_byte_t *data;
- struct id3_tag *tag = 0;
-
- data = malloc(size);
- if (data) {
- if (vfs_fread(data, size, 1, iofile) == 1)
- tag = id3_tag_parse(data, size);
-
- free(data);
- }
-
- return tag;
-}
-
-/*
- * NAME: update_primary()
- * DESCRIPTION: update the primary tag with data from a new tag
- */
-static
-int update_primary(struct id3_tag *tag, struct id3_tag const *new)
-{
- unsigned int i;
- struct id3_frame *frame;
-
- if (new) {
- if (!(new->extendedflags & ID3_TAG_EXTENDEDFLAG_TAGISANUPDATE))
- id3_tag_clearframes(tag);
-
- i = 0;
- while ((frame = id3_tag_findframe(new, 0, i++))) {
- if (id3_tag_attachframe(tag, frame) == -1)
- return -1;
- }
- }
-
- return 0;
-}
-
-/*
- * NAME: tag_compare()
- * DESCRIPTION: tag sort function for qsort()
- */
-static
-int tag_compare(const void *a, const void *b)
-{
- struct filetag const *tag1 = a, *tag2 = b;
-
- if (tag1->location < tag2->location)
- return -1;
- else if (tag1->location > tag2->location)
- return +1;
-
- return 0;
-}
-
-/*
- * NAME: add_filetag()
- * DESCRIPTION: add a new file tag entry
- */
-static
-int add_filetag(struct id3_file *file, struct filetag const *filetag)
-{
- struct filetag *tags;
-
- tags = realloc(file->tags, (file->ntags + 1) * sizeof(*tags));
- if (tags == 0)
- return -1;
-
- file->tags = tags;
- file->tags[file->ntags++] = *filetag;
-
- /* sort tags by location */
-
- if (file->ntags > 1)
- qsort(file->tags, file->ntags, sizeof(file->tags[0]), tag_compare);
-
- return 0;
-}
-
-/*
- * NAME: del_filetag()
- * DESCRIPTION: delete a file tag entry
- */
-/*
-static
-void del_filetag(struct id3_file *file, unsigned int index)
-{
- assert(index < file->ntags);
-
- while (index < file->ntags - 1) {
- file->tags[index] = file->tags[index + 1];
- ++index;
- }
-
- --file->ntags;
-}
-*/
-
-/*
- * NAME: add_tag()
- * DESCRIPTION: read, parse, and add a tag to a file structure
- */
-static
-struct id3_tag *add_tag(struct id3_file *file, id3_length_t length)
-{
- long location;
- unsigned int i;
- struct filetag filetag;
- struct id3_tag *tag;
-
- location = vfs_ftell(file->iofile);
- if (location == -1)
- return 0;
-
- /* check for duplication/overlap */
- {
- unsigned long begin1, end1, begin2, end2;
-
- begin1 = location;
- end1 = begin1 + length;
-
- for (i = 0; i < file->ntags; ++i) {
- begin2 = file->tags[i].location;
- end2 = begin2 + file->tags[i].length;
-
- if (begin1 == begin2 && end1 == end2)
- return file->tags[i].tag; /* duplicate */
-
- if (begin1 < end2 && end1 > begin2)
- return 0; /* overlap */
- }
- }
-
- tag = read_tag(file->iofile, length);
-
- filetag.tag = tag;
- filetag.location = location;
- filetag.length = length;
-
- if (add_filetag(file, &filetag) == -1 ||
- update_primary(file->primary, tag) == -1) {
- if (tag)
- id3_tag_delete(tag);
- return 0;
- }
-
- if (tag)
- id3_tag_addref(tag);
-
- return tag;
-}
-
-/*
- * NAME: search_tags()
- * DESCRIPTION: search for tags in a file
- */
-//static
-int search_tags(struct id3_file *file)
-{
- int save_position;
- signed long size;
-
- /*
- * save the current seek position
- *
- * We also verify the stream is seekable by calling fsetpos(), since
- * fgetpos() alone is not reliable enough for this purpose.
- *
- * [Apparently not even fsetpos() is sufficient under Win32.]
- */
-
-// if (fgetpos(file->iofile, &save_position) == -1 ||
-// fsetpos(file->iofile, &save_position) == -1)
-// if (save_position = vfs_ftell(file->iofile) == -1 ||
-// vfs_fseek(file->iofile, save_position, SEEK_SET) == -1)
- if((save_position = vfs_ftell(file->iofile)) == -1)
- return -1;
-
- /* look for an ID3v1 tag */
-
- if (vfs_fseek(file->iofile, -128, SEEK_END) == 0) {
- size = query_tag(file->iofile);
- if (size > 0) {
- struct id3_tag const *tag;
-
- tag = add_tag(file, size);
-
- /* if this is indeed an ID3v1 tag, mark the file so */
-
- if (tag && (ID3_TAG_VERSION_MAJOR(id3_tag_version(tag)) == 1))
- file->flags |= ID3_FILE_FLAG_ID3V1;
- }
- }
-
- /* look for a tag at the beginning of the file */
-
- vfs_rewind(file->iofile);
-
- size = query_tag(file->iofile);
- if (size > 0) {
- struct id3_tag const *tag;
- struct id3_frame const *frame;
-
- tag = add_tag(file, size);
-
- /* locate tags indicated by SEEK frames */
-
- while (tag && (frame = id3_tag_findframe(tag, "SEEK", 0))) {
- long seek;
-
- seek = id3_field_getint(id3_frame_field(frame, 0));
- if (seek < 0 || vfs_fseek(file->iofile, seek, SEEK_CUR) == -1)
- break;
-
- size = query_tag(file->iofile);
- tag = (size > 0) ? add_tag(file, size) : 0;
- }
- }
-
- /* look for a tag at the end of the file (before any ID3v1 tag) */
-
- if (vfs_fseek(file->iofile, ((file->flags & ID3_FILE_FLAG_ID3V1) ? -128 : 0) +
- -10, SEEK_END) == 0) {
- size = query_tag(file->iofile);
- if (size < 0 && vfs_fseek(file->iofile, size, SEEK_CUR) == 0) {
- size = query_tag(file->iofile);
- if (size > 0)
- add_tag(file, size);
- }
- }
-
-#ifndef AUDACIOUS
- clearerr(file->iofile);
-#endif
-
- /* restore seek position */
-
- if (vfs_fseek(file->iofile, save_position, SEEK_SET) == -1)
- return -1;
-
- /* set primary tag options and target padded length for convenience */
-
- if ((file->ntags > 0 && !(file->flags & ID3_FILE_FLAG_ID3V1)) ||
- (file->ntags > 1 && (file->flags & ID3_FILE_FLAG_ID3V1))) {
- if (file->tags[0].location == 0)
- id3_tag_setlength(file->primary, file->tags[0].length);
- else
- id3_tag_options(file->primary, ID3_TAG_OPTION_APPENDEDTAG, ~0);
- }
-
- return 0;
-}
-
-/*
- * NAME: finish_file()
- * DESCRIPTION: release memory associated with a file
- */
-static
-void finish_file(struct id3_file *file)
-{
- unsigned int i;
-
- if (file->path)
- free(file->path);
-
- if (file->primary) {
- id3_tag_delref(file->primary);
- id3_tag_delete(file->primary);
- }
-
- for (i = 0; i < file->ntags; ++i) {
- struct id3_tag *tag;
-
- tag = file->tags[i].tag;
- if (tag) {
- id3_tag_delref(tag);
- id3_tag_delete(tag);
- }
- }
-
- if (file->tags)
- free(file->tags);
-
- free(file);
-}
-
-/*
- * NAME: new_file()
- * DESCRIPTION: create a new file structure and load tags
- */
-static
-struct id3_file *new_file(VFSFile *iofile, enum id3_file_mode mode,
- char const *path)
-{
- struct id3_file *file;
-
- file = malloc(sizeof(*file));
- if (file == 0)
- goto fail;
-
- file->iofile = iofile;
- file->mode = mode;
- file->path = path ? strdup(path) : 0;
-
- file->flags = 0;
-
- file->ntags = 0;
- file->tags = 0;
-
- file->primary = id3_tag_new();
- if (file->primary == 0)
- goto fail;
-
- id3_tag_addref(file->primary);
-
- /* load tags from the file */
-
- if (search_tags(file) == -1)
- goto fail;
-
- id3_tag_options(file->primary, ID3_TAG_OPTION_ID3V1,
- (file->flags & ID3_FILE_FLAG_ID3V1) ? ~0 : 0);
-
- if (0) {
- fail:
- if (file) {
- finish_file(file);
- file = 0;
- }
- }
-
- return file;
-}
-
-
-/*
- * NAME: file->open()
- * DESCRIPTION: open a file given its pathname
- */
-struct id3_file *id3_file_open(char const *path, enum id3_file_mode mode)
-{
- VFSFile *iofile;
- struct id3_file *file;
-
- assert(path);
-
- iofile = vfs_fopen(path, (mode == ID3_FILE_MODE_READWRITE) ? "r+b" : "rb");
- if (iofile == 0){
- printf("id3_file_open: iofile failed\n");
- return 0;
- }
- file = new_file(iofile, mode, path);
- if (file == 0){
- printf("id3_file_open: file failed\n");
- vfs_fclose(iofile);
- }
-
- return file;
-}
-
-/*
- * NAME: file->vfsopen()
- * DESCRIPTION: open a file given its vfs
- */
-struct id3_file *id3_file_vfsopen(VFSFile *iofile, enum id3_file_mode mode)
-{
- struct id3_file *file;
- glong curpos;
- gchar *path;
-
- assert(iofile);
-
- path = iofile->uri;
-
- vfs_dup(iofile);
-
- curpos = vfs_ftell(iofile);
- vfs_fseek(iofile, 0, SEEK_SET);
-
- file = new_file(iofile, mode, path);
- if (file == 0){
- printf("id3_file_vfsopen: file failed\n");
- vfs_fclose(iofile);
- }
-
- vfs_fseek(iofile, curpos, SEEK_SET);
-
- return file;
-}
-
-/*
- * NAME: file->fdopen()
- * DESCRIPTION: open a file using an existing file descriptor
- */
-#ifndef AUDACIOUS
-struct id3_file *id3_file_fdopen(int fd, enum id3_file_mode mode)
-{
-# if 1 || defined(HAVE_UNISTD_H)
- VFSFile *iofile;
- struct id3_file *file;
-
- iofile = fdopen(fd, (mode == ID3_FILE_MODE_READWRITE) ? "r+b" : "rb");
- if (iofile == 0)
- return 0;
-
- file = new_file(iofile, mode, 0);
- if (file == 0) {
- int save_fd;
-
- /* close iofile without closing fd */
-
- save_fd = dup(fd);
-
- fclose(iofile);
-
- dup2(save_fd, fd);
- close(save_fd);
- }
-
- return file;
-# else
- return 0;
-# endif
-}
-#endif
-
-/*
- * NAME: file->close()
- * DESCRIPTION: close a file and delete its associated tags
- */
-int id3_file_close(struct id3_file *file)
-{
- int result = 0;
-
- assert(file);
-
- if (vfs_fclose(file->iofile) == EOF)
- result = -1;
-
- finish_file(file);
-
- return result;
-}
-
-/*
- * NAME: file->tag()
- * DESCRIPTION: return the primary tag structure for a file
- */
-struct id3_tag *id3_file_tag(struct id3_file const *file)
-{
- assert(file);
-
- return file->primary;
-}
-
-/*
- * NAME: v1_write()
- * DESCRIPTION: write ID3v1 tag modifications to a file
- */
-static
-int v1_write(struct id3_file *file,
- id3_byte_t const *data, id3_length_t length)
-{
-// assert(!data || length == 128);
-
- if (data) {
- long location;
-
- if (vfs_fseek(file->iofile, (file->flags & ID3_FILE_FLAG_ID3V1) ? -128 : 0,
- SEEK_END) == -1 ||
- (location = vfs_ftell(file->iofile)) == -1 ||
-#ifdef AUDACIOUS
- vfs_fwrite(data, 128, 1, file->iofile) != 1 )
-#else
- vfs_fwrite(data, 128, 1, file->iofile) != 1 ||
- fflush(file->iofile) == EOF) //XXX
-#endif
- return -1;
-
- /* add file tag reference */
-
- if (!(file->flags & ID3_FILE_FLAG_ID3V1)) {
- struct filetag filetag;
-
- filetag.tag = 0;
- filetag.location = location;
- filetag.length = 128;
-
- if (add_filetag(file, &filetag) == -1)
- return -1;
-
- file->flags |= ID3_FILE_FLAG_ID3V1;
- }
- }
-# if defined(HAVE_FTRUNCATE)
- else if (file->flags & ID3_FILE_FLAG_ID3V1) {
- long length;
-
- if (vfs_fseek(file->iofile, 0, SEEK_END) == -1)
- return -1;
-
- length = vfs_ftell(file->iofile);
- if (length == -1 ||
- (length >= 0 && length < 128))
- return -1;
-
- if (vfs_truncate(file->iofile, length - 128) == -1)
- return -1;
-
- /* delete file tag reference */
-
- del_filetag(file, file->ntags - 1);
-
- file->flags &= ~ID3_FILE_FLAG_ID3V1;
- }
-# endif
-
- return 0;
-}
-
-/*
- * NAME: v2_write()
- * DESCRIPTION: write ID3v2 tag modifications to a file
- */
-static
-int v2_write(struct id3_file *file,
- id3_byte_t const *data, id3_length_t length)
-{
-// assert(!data || length > 0);
-
- // delete tag request
- if(!data && length == 0){
- int file_size;
- int remainder_size;
- char *remainder;
-
- /* read in the remainder of the file */
- vfs_fseek(file->iofile, 0, SEEK_END);
- file_size = vfs_ftell(file->iofile);
- remainder_size = file_size - file->tags[0].location - file->tags[0].length;
- remainder = (char*)malloc(remainder_size);
-
- if (vfs_fseek(file->iofile, file->tags[0].location + file->tags[0].length, SEEK_SET) == -1 ||
- vfs_fread(remainder, remainder_size, 1, file->iofile) != 1) {
- free(remainder);
- return -1;
- }
-
- /* write the remainder where the old tag was */
- if (vfs_fseek(file->iofile, file->tags[0].location, SEEK_SET) == -1 ||
- vfs_fwrite(remainder, remainder_size, 1, file->iofile) != 1) {
- free(remainder);
- return -1;
- }
-
- free(remainder);
-
- /* flush the FILE */
-#ifndef AUDACIOUS
- if (fflush(file->iofile) == EOF)
- return -1;
-#endif
- /* truncate if required */
- if (vfs_ftell(file->iofile) < file_size)
- vfs_truncate(file->iofile, vfs_ftell(file->iofile));
-
- }
-
- // append a new id3v2 tag to the file which doesn't have any tag or only have v1tag.
- if(data &&
- ((file->ntags == 0) || // no tag
- (file->ntags == 1 && (file->flags & ID3_FILE_FLAG_ID3V1))) ) { // only v1 tag exists
-
- struct filetag filetag;
-
- printf("append v2tag\n");
-
- filetag.tag = 0;
- filetag.location = 0; // begining of the file.
- filetag.length = 0;
-
- if(add_filetag(file, &filetag) == -1)
- return -1;
-
- if(file->ntags == 1)
- file->flags = 0;
- if(file->ntags == 2)
- file->flags |= ID3_FILE_FLAG_ID3V1;
- }
-
- if (!data
- || (!(file->ntags == 1 && !(file->flags & ID3_FILE_FLAG_ID3V1)) &&
- !(file->ntags == 2 && (file->flags & ID3_FILE_FLAG_ID3V1)))) {
- /* no v2 tag. nothing to do */
- goto done;
- }
-
- if (file->tags[0].length == length) {
- /* easy special case: rewrite existing tag in-place */
-
- if (vfs_fseek(file->iofile, file->tags[0].location, SEEK_SET) == -1 ||
-#ifdef AUDACIOUS
- vfs_fwrite(data, length, 1, file->iofile) != 1)
-#else
- vfs_fwrite(data, length, 1, file->iofile) != 1 ||
- fflush(file->iofile) == EOF)
-#endif
- return -1;
-
- goto done;
- } else {
- /* the new tag has a different size */
- int file_size;
- int remainder_size;
- char *remainder;
-
- /* read in the remainder of the file */
- vfs_fseek(file->iofile, 0, SEEK_END);
- file_size = vfs_ftell(file->iofile);
- remainder_size = file_size - file->tags[0].location - file->tags[0].length;
- remainder = (char*)malloc(remainder_size);
- if (vfs_fseek(file->iofile, file->tags[0].location + file->tags[0].length, SEEK_SET) == -1 ||
- vfs_fread(remainder, remainder_size, 1, file->iofile) != 1) {
- free(remainder);
- return -1;
- }
-
- /* write the tag where the old one was */
- if (vfs_fseek(file->iofile, file->tags[0].location, SEEK_SET) == -1 ||
- vfs_fwrite(data, length, 1, file->iofile) != 1) {
- free(remainder);
- return -1;
- }
-
- /* write the reaminder */
- if (vfs_fwrite(remainder, remainder_size, 1, file->iofile) != 1) {
- free(remainder);
- return -1;
- }
-
- free(remainder);
-
- /* flush the FILE */
-#ifndef AUDACIOUS
- if (fflush(file->iofile) == EOF)
- return -1;
-#endif
- /* truncate if required */
- if (vfs_ftell(file->iofile) < file_size)
- vfs_truncate(file->iofile, vfs_ftell(file->iofile));
- }
-
- done:
- return 0;
-}
-
-/*
- * NAME: file->update()
- * DESCRIPTION: rewrite tag(s) to a file
- */
-int id3_file_update(struct id3_file *file)
-{
- int options, result = 0;
- id3_length_t v1size = 0, v2size = 0;
- id3_byte_t id3v1_data[128], *id3v1 = 0, *id3v2 = 0;
-
- assert(file);
-
- if (file->mode != ID3_FILE_MODE_READWRITE)
- return -1;
-
- options = id3_tag_options(file->primary, 0, 0);
-
- /* render ID3v1 */
-
- if (options & ID3_TAG_OPTION_ID3V1) {
- v1size = id3_tag_render(file->primary, 0);
- if (v1size) {
- assert(v1size == sizeof(id3v1_data));
-
- v1size = id3_tag_render(file->primary, id3v1_data);
- if (v1size) {
- assert(v1size == sizeof(id3v1_data));
- id3v1 = id3v1_data;
- }
- }
- }
-
- /* render ID3v2 */
-
- id3_tag_options(file->primary, ID3_TAG_OPTION_ID3V1, 0);
-
- v2size = id3_tag_render(file->primary, 0);
- if (v2size) {
- id3v2 = malloc(v2size);
- if (id3v2 == 0)
- goto fail;
-
- v2size = id3_tag_render(file->primary, id3v2);
- if (v2size == 0) {
- free(id3v2);
- id3v2 = 0;
- }
- }
-
- /* write tags */
-
- if (v2_write(file, id3v2, v2size) == -1 &&
- v1_write(file, id3v1, v1size) == -1)
- goto fail;
-
- vfs_rewind(file->iofile);
-
- /* update file tags array? ... */
-
- if (0) {
- fail:
- result = -1;
- }
-
- /* clean up; restore tag options */
-
- if (id3v2)
- free(id3v2);
-
- id3_tag_options(file->primary, ~0, options);
-
- return result;
-}
diff --git a/src/libid3tag/file.h b/src/libid3tag/file.h
deleted file mode 100644
index 032b189..0000000
--- a/src/libid3tag/file.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: file.h,v 1.8 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_FILE_H
-# define LIBID3TAG_FILE_H
-
-# endif
diff --git a/src/libid3tag/frame.c b/src/libid3tag/frame.c
deleted file mode 100644
index 08710ff..0000000
--- a/src/libid3tag/frame.c
+++ /dev/null
@@ -1,627 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: frame.c,v 1.15 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <stdlib.h>
-# include <stdio.h>
-# include <string.h>
-
-# ifdef HAVE_ASSERT_H
-# include <assert.h>
-# endif
-
-# include "id3tag.h"
-# include "frame.h"
-# include "frametype.h"
-# include "compat.h"
-# include "field.h"
-# include "render.h"
-# include "parse.h"
-# include "util.h"
-
-static
-int valid_idchar(char c)
-{
- return (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
-}
-
-/*
- * NAME: frame->validid()
- * DESCRIPTION: return true if the parameter string is a legal frame ID
- */
-int id3_frame_validid(char const *id)
-{
- return id &&
- valid_idchar(id[0]) &&
- valid_idchar(id[1]) &&
- valid_idchar(id[2]) &&
- valid_idchar(id[3]);
-}
-
-/*
- * NAME: frame->new()
- * DESCRIPTION: allocate and return a new frame
- */
-struct id3_frame *id3_frame_new(char const *id)
-{
- struct id3_frametype const *frametype;
- struct id3_frame *frame;
- unsigned int i;
-
- if (!id3_frame_validid(id))
- return 0;
-
- frametype = id3_frametype_lookup(id, 4);
- if (frametype == 0) {
- switch (id[0]) {
- case 'T':
- frametype = &id3_frametype_text;
- break;
-
- case 'W':
- frametype = &id3_frametype_url;
- break;
-
- case 'X':
- case 'Y':
- case 'Z':
- frametype = &id3_frametype_experimental;
- break;
-
- default:
- frametype = &id3_frametype_unknown;
- if (id3_compat_lookup(id, 4))
- frametype = &id3_frametype_obsolete;
- break;
- }
- }
-
- frame = malloc(sizeof(*frame) + frametype->nfields * sizeof(*frame->fields));
- if (frame) {
- frame->id[0] = id[0];
- frame->id[1] = id[1];
- frame->id[2] = id[2];
- frame->id[3] = id[3];
- frame->id[4] = 0;
-
- frame->description = frametype->description;
- frame->refcount = 0;
- frame->flags = frametype->defaultflags;
- frame->group_id = 0;
- frame->encryption_method = 0;
- frame->encoded = 0;
- frame->encoded_length = 0;
- frame->decoded_length = 0;
- frame->nfields = frametype->nfields;
- frame->fields = (union id3_field *) &frame[1];
-
- for (i = 0; i < frame->nfields; ++i)
- id3_field_init(&frame->fields[i], frametype->fields[i]);
- }
-
- return frame;
-}
-
-void id3_frame_delete(struct id3_frame *frame)
-{
- assert(frame);
-
- if (frame->refcount == 0) {
- unsigned int i;
-
- for (i = 0; i < frame->nfields; ++i)
- id3_field_finish(&frame->fields[i]);
-
- if (frame->encoded)
- free(frame->encoded);
-
- free(frame);
- }
-}
-
-/*
- * NAME: frame->addref()
- * DESCRIPTION: add an external reference to a frame
- */
-void id3_frame_addref(struct id3_frame *frame)
-{
- assert(frame);
-
- ++frame->refcount;
-}
-
-/*
- * NAME: frame->delref()
- * DESCRIPTION: remove an external reference to a frame
- */
-void id3_frame_delref(struct id3_frame *frame)
-{
- assert(frame && frame->refcount > 0);
-
- --frame->refcount;
-}
-
-/*
- * NAME: frame->field()
- * DESCRIPTION: return a pointer to a field in a frame
- */
-union id3_field *id3_frame_field(struct id3_frame const *frame,
- unsigned int index)
-{
- assert(frame);
-
- return (index < frame->nfields) ? &frame->fields[index] : 0;
-}
-
-static
-struct id3_frame *obsolete(char const *id, id3_byte_t const *data,
- id3_length_t length)
-{
- struct id3_frame *frame;
-
- frame = id3_frame_new(ID3_FRAME_OBSOLETE);
- if (frame) {
- if (id3_field_setframeid(&frame->fields[0], id) == -1 ||
- id3_field_setbinarydata(&frame->fields[1], data, length) == -1)
- goto fail;
- }
-
- if (0) {
- fail:
- if (frame) {
- id3_frame_delete(frame);
- frame = 0;
- }
- }
-
- return frame;
-}
-
-static
-struct id3_frame *unparseable(char const *id, id3_byte_t const **ptr,
- id3_length_t length, int flags,
- int group_id, int encryption_method,
- id3_length_t decoded_length)
-{
- struct id3_frame *frame = 0;
- id3_byte_t *mem;
-
- mem = malloc(length ? length : 1);
- if (mem == 0)
- goto fail;
-
- frame = id3_frame_new(id);
- if (frame == 0)
- free(mem);
- else {
- memcpy(mem, *ptr, length);
-
- frame->flags = flags;
- frame->group_id = group_id;
- frame->encryption_method = encryption_method;
- frame->encoded = mem;
- frame->encoded_length = length;
- frame->decoded_length = decoded_length;
- }
-
- if (0) {
- fail:
- ;
- }
-
- *ptr += length;
-
- return frame;
-}
-
-static
-int parse_data(struct id3_frame *frame,
- id3_byte_t const *data, id3_length_t length)
-{
- enum id3_field_textencoding encoding;
- id3_byte_t const *end;
- unsigned int i;
-
- encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1;
-
- end = data + length;
-
- for (i = 0; i < frame->nfields; ++i) {
- if (id3_field_parse(&frame->fields[i], &data, end - data, &encoding) == -1)
- return -1;
- }
-
- return 0;
-}
-
-/*
- * NAME: frame->parse()
- * DESCRIPTION: parse raw frame data according to the specified ID3 tag version
- */
-struct id3_frame *id3_frame_parse(id3_byte_t const **ptr, id3_length_t length,
- unsigned int version)
-{
- struct id3_frame *frame = 0;
- id3_byte_t const *id, *end, *data;
- id3_length_t size, decoded_length = 0;
- int flags = 0, group_id = 0, encryption_method = 0;
- struct id3_compat const *compat = 0;
- id3_byte_t *mem = 0;
- char xid[4];
-
- id = *ptr;
- end = *ptr + length;
-
- if (ID3_TAG_VERSION_MAJOR(version) < 4) {
- switch (ID3_TAG_VERSION_MAJOR(version)) {
- case 2:
- if (length < 6)
- goto fail;
-
- compat = id3_compat_lookup((char *)id, 3);
-
- *ptr += 3;
- size = id3_parse_uint(ptr, 3);
-
- if (size > end - *ptr)
- goto fail;
-
- end = *ptr + size;
-
- break;
-
- case 3:
- if (length < 10)
- goto fail;
-
- compat = id3_compat_lookup((char *)id, 4);
-
- *ptr += 4;
- size = id3_parse_uint(ptr, 4);
- flags = id3_parse_uint(ptr, 2);
-
- if (size > end - *ptr)
- goto fail;
-
- end = *ptr + size;
-
- if (flags & (ID3_FRAME_FLAG_FORMATFLAGS & ~0x00e0)) {
- frame = unparseable((char *)id, ptr, end - *ptr, 0, 0, 0, 0);
- goto done;
- }
-
- flags =
- ((flags >> 1) & ID3_FRAME_FLAG_STATUSFLAGS) |
- ((flags >> 4) & (ID3_FRAME_FLAG_COMPRESSION |
- ID3_FRAME_FLAG_ENCRYPTION)) |
- ((flags << 1) & ID3_FRAME_FLAG_GROUPINGIDENTITY);
-
- if (flags & ID3_FRAME_FLAG_COMPRESSION) {
- if (end - *ptr < 4)
- goto fail;
-
- decoded_length = id3_parse_uint(ptr, 4);
- }
-
- if (flags & ID3_FRAME_FLAG_ENCRYPTION) {
- if (end - *ptr < 1)
- goto fail;
-
- encryption_method = id3_parse_uint(ptr, 1);
- }
-
- if (flags & ID3_FRAME_FLAG_GROUPINGIDENTITY) {
- if (end - *ptr < 1)
- goto fail;
-
- group_id = id3_parse_uint(ptr, 1);
- }
-
- break;
-
- default:
- goto fail;
- }
-
- /* canonicalize frame ID for ID3v2.4 */
-
- if (compat && compat->equiv)
- id = (id3_byte_t *)compat->equiv;
- else if (ID3_TAG_VERSION_MAJOR(version) == 2) {
- xid[0] = 'Y';
- xid[1] = id[0];
- xid[2] = id[1];
- xid[3] = id[2];
-
- id = (id3_byte_t *)xid;
-
- flags |=
- ID3_FRAME_FLAG_TAGALTERPRESERVATION |
- ID3_FRAME_FLAG_FILEALTERPRESERVATION;
- }
- }
- else { /* ID3v2.4 */
- if (length < 10)
- goto fail;
-
- *ptr += 4;
- size = id3_parse_syncsafe(ptr, 4);
- flags = id3_parse_uint(ptr, 2);
-
- if (size > end - *ptr)
- goto fail;
-
- end = *ptr + size;
-
- if (flags & (ID3_FRAME_FLAG_FORMATFLAGS & ~ID3_FRAME_FLAG_KNOWNFLAGS)) {
- frame = unparseable((char *)id, ptr, end - *ptr, flags, 0, 0, 0);
- goto done;
- }
-
- if (flags & ID3_FRAME_FLAG_GROUPINGIDENTITY) {
- if (end - *ptr < 1)
- goto fail;
-
- group_id = id3_parse_uint(ptr, 1);
- }
-
- if ((flags & ID3_FRAME_FLAG_COMPRESSION) &&
- !(flags & ID3_FRAME_FLAG_DATALENGTHINDICATOR))
- goto fail;
-
- if (flags & ID3_FRAME_FLAG_ENCRYPTION) {
- if (end - *ptr < 1)
- goto fail;
-
- encryption_method = id3_parse_uint(ptr, 1);
- }
-
- if (flags & ID3_FRAME_FLAG_DATALENGTHINDICATOR) {
- if (end - *ptr < 4)
- goto fail;
-
- decoded_length = id3_parse_syncsafe(ptr, 4);
- }
- }
-
- data = *ptr;
- *ptr = end;
-
- /* undo frame encodings */
-
- if ((flags & ID3_FRAME_FLAG_UNSYNCHRONISATION) && end - data > 0) {
- mem = malloc(end - data);
- if (mem == 0)
- goto fail;
-
- memcpy(mem, data, end - data);
-
- end = mem + id3_util_deunsynchronise(mem, end - data);
- data = mem;
- }
-
- if (flags & ID3_FRAME_FLAG_ENCRYPTION) {
- frame = unparseable((char *)id, &data, end - data, flags,
- group_id, encryption_method, decoded_length);
- goto done;
- }
-
- if (flags & ID3_FRAME_FLAG_COMPRESSION) {
- id3_byte_t *decomp;
-
- decomp = id3_util_decompress(data, end - data, decoded_length);
- if (decomp == 0)
- goto fail;
-
- if (mem)
- free(mem);
-
- data = mem = decomp;
- end = data + decoded_length;
- }
-
- /* check for obsolescence */
-
- if (compat && !compat->equiv) {
- frame = obsolete((char *)id, data, end - data);
- goto done;
- }
-
- /* generate the internal frame structure */
-
- frame = id3_frame_new((char *)id);
- if (frame) {
- frame->flags = flags;
- frame->group_id = group_id;
-
- if (compat && compat->translate) {
- if (compat->translate(frame, compat->id, data, end - data) == -1)
- goto fail;
- }
- else {
- if (parse_data(frame, data, end - data) == -1)
- goto fail;
- }
- }
-
- if (0) {
- fail:
- if (frame) {
- id3_frame_delete(frame);
- frame = 0;
- }
- }
-
- done:
- if (mem)
- free(mem);
-
- return frame;
-}
-
-static
-id3_length_t render_data(id3_byte_t **ptr,
- union id3_field *fields, unsigned int length)
-{
- id3_length_t size = 0;
- enum id3_field_textencoding encoding;
- unsigned int i;
-
- encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1; //here!! --yaz
- fflush(NULL);
- for (i = 0; i < length; ++i)
- size += id3_field_render(&fields[i], ptr, &encoding, i < length - 1);
-
- return size;
-}
-
-/*
- * NAME: frame->render()
- * DESCRIPTION: render a single, complete frame
- */
-id3_length_t id3_frame_render(struct id3_frame const *frame,
- id3_byte_t **ptr, int options)
-{
- id3_length_t size = 0, decoded_length, datalen;
- id3_byte_t *size_ptr = 0, *flags_ptr = 0, *data = 0;
- int flags;
-
- assert(frame);
-
- if ((frame->flags & ID3_FRAME_FLAG_TAGALTERPRESERVATION) ||
- ((options & ID3_TAG_OPTION_FILEALTERED) &&
- (frame->flags & ID3_FRAME_FLAG_FILEALTERPRESERVATION)))
- return 0;
-
- /* a frame must be at least 1 byte big, excluding the header */
-
- decoded_length = render_data(0, frame->fields, frame->nfields);
- if (decoded_length == 0 && frame->encoded == 0)
- return 0;
-
- /* header */
-
- size += id3_render_immediate(ptr, frame->id, 4);
-
- if (ptr)
- size_ptr = *ptr;
-
- size += id3_render_syncsafe(ptr, 0, 4);
-
- if (ptr)
- flags_ptr = *ptr;
-
- flags = frame->flags;
-
- size += id3_render_int(ptr, flags, 2);
-
- if (flags & (ID3_FRAME_FLAG_FORMATFLAGS & ~ID3_FRAME_FLAG_KNOWNFLAGS)) {
- size += id3_render_binary(ptr, frame->encoded, frame->encoded_length);
- if (size_ptr)
- id3_render_syncsafe(&size_ptr, size - 10, 4);
-
- return size;
- }
-
- flags &= ID3_FRAME_FLAG_KNOWNFLAGS;
-
- flags &= ~ID3_FRAME_FLAG_UNSYNCHRONISATION;
- if (options & ID3_TAG_OPTION_UNSYNCHRONISATION)
- flags |= ID3_FRAME_FLAG_UNSYNCHRONISATION;
-
- if (!(flags & ID3_FRAME_FLAG_ENCRYPTION)) {
- flags &= ~ID3_FRAME_FLAG_COMPRESSION;
- if (options & ID3_TAG_OPTION_COMPRESSION)
- flags |= ID3_FRAME_FLAG_COMPRESSION | ID3_FRAME_FLAG_DATALENGTHINDICATOR;
- }
-
- if (flags & ID3_FRAME_FLAG_GROUPINGIDENTITY)
- size += id3_render_int(ptr, frame->group_id, 1);
- if (flags & ID3_FRAME_FLAG_ENCRYPTION)
- size += id3_render_int(ptr, frame->encryption_method, 1);
- if (flags & ID3_FRAME_FLAG_DATALENGTHINDICATOR) {
- if (flags & ID3_FRAME_FLAG_ENCRYPTION)
- decoded_length = frame->decoded_length;
- size += id3_render_syncsafe(ptr, decoded_length, 4);
- }
-
- if (ptr)
- data = *ptr;
-
- if (flags & ID3_FRAME_FLAG_ENCRYPTION)
- datalen = id3_render_binary(ptr, frame->encoded, frame->encoded_length);
- else {
- if (ptr == 0)
- datalen = decoded_length;
- else {
- datalen = render_data(ptr, frame->fields, frame->nfields);
-
- if (flags & ID3_FRAME_FLAG_COMPRESSION) {
- id3_byte_t *comp;
- id3_length_t complen;
-
- comp = id3_util_compress(data, datalen, &complen);
- if (comp == 0)
- flags &= ~ID3_FRAME_FLAG_COMPRESSION;
- else {
- *ptr = data;
- datalen = id3_render_binary(ptr, comp, complen);
-
- free(comp);
- }
- }
- }
- }
-
- /* unsynchronisation */
-
- if (flags & ID3_FRAME_FLAG_UNSYNCHRONISATION) {
- if (data == 0)
- datalen *= 2;
- else {
- id3_length_t newlen;
-
- newlen = id3_util_unsynchronise(data, datalen);
- if (newlen == datalen)
- flags &= ~ID3_FRAME_FLAG_UNSYNCHRONISATION;
- else {
- *ptr += newlen - datalen;
- datalen = newlen;
- }
- }
- }
-
- size += datalen;
-
- /* patch size and flags */
-
- if (size_ptr)
- id3_render_syncsafe(&size_ptr, size - 10, 4);
- if (flags_ptr)
- id3_render_int(&flags_ptr, flags, 2);
-
- return size;
-}
diff --git a/src/libid3tag/frame.h b/src/libid3tag/frame.h
deleted file mode 100644
index 05c6b04..0000000
--- a/src/libid3tag/frame.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: frame.h,v 1.8 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_FRAME_H
-# define LIBID3TAG_FRAME_H
-
-# include "id3tag.h"
-
-int id3_frame_validid(char const *);
-
-void id3_frame_addref(struct id3_frame *);
-void id3_frame_delref(struct id3_frame *);
-
-struct id3_frame *id3_frame_parse(id3_byte_t const **, id3_length_t,
- unsigned int);
-id3_length_t id3_frame_render(struct id3_frame const *, id3_byte_t **, int);
-
-# endif
diff --git a/src/libid3tag/frametype.c b/src/libid3tag/frametype.c
deleted file mode 100644
index 13c5001..0000000
--- a/src/libid3tag/frametype.c
+++ /dev/null
@@ -1,568 +0,0 @@
-/* C code produced by gperf version 3.0.1 */
-/* Command-line: gperf -tCcTonD -K id -N id3_frametype_lookup -s -3 -k '*' frametype.gperf */
-
-#if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
- && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
- && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
- && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
- && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
- && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
- && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
- && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
- && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
- && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
- && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
- && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
- && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
- && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
- && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
- && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
- && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
- && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
- && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
- && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
- && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
- && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
- && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
-/* The character set is not based on ISO-646. */
-error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
-#endif
-
-#line 1 "frametype.gperf"
-
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Id: frametype.gperf,v 1.7 2004/01/23 09:41:32 rob Exp
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <string.h>
-
-# include "id3tag.h"
-# include "frametype.h"
-
-# define FIELDS(id) static enum id3_field_type const fields_##id[]
-
-/* frame field descriptions */
-
-FIELDS(UFID) = {
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(TXXX) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_STRING
-};
-
-FIELDS(WXXX) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_LATIN1
-};
-
-FIELDS(MCDI) = {
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(ETCO) = {
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(MLLT) = {
- ID3_FIELD_TYPE_INT16,
- ID3_FIELD_TYPE_INT24,
- ID3_FIELD_TYPE_INT24,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(SYTC) = {
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(USLT) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LANGUAGE,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_STRINGFULL
-};
-
-FIELDS(SYLT) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LANGUAGE,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(COMM) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LANGUAGE,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_STRINGFULL
-};
-
-FIELDS(RVA2) = {
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(EQU2) = {
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(RVRB) = {
- ID3_FIELD_TYPE_INT16,
- ID3_FIELD_TYPE_INT16,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8
-};
-
-FIELDS(APIC) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(GEOB) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(PCNT) = {
- ID3_FIELD_TYPE_INT32PLUS
-};
-
-FIELDS(POPM) = {
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT32PLUS
-};
-
-FIELDS(RBUF) = {
- ID3_FIELD_TYPE_INT24,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT32
-};
-
-FIELDS(AENC) = {
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_INT16,
- ID3_FIELD_TYPE_INT16,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(LINK) = {
- ID3_FIELD_TYPE_FRAMEID,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_LATIN1LIST
-};
-
-FIELDS(POSS) = {
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(USER) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LANGUAGE,
- ID3_FIELD_TYPE_STRING
-};
-
-FIELDS(OWNE) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_DATE,
- ID3_FIELD_TYPE_STRING
-};
-
-FIELDS(COMR) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_DATE,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(ENCR) = {
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(GRID) = {
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(PRIV) = {
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(SIGN) = {
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(SEEK) = {
- ID3_FIELD_TYPE_INT32
-};
-
-FIELDS(ASPI) = {
- ID3_FIELD_TYPE_INT32,
- ID3_FIELD_TYPE_INT32,
- ID3_FIELD_TYPE_INT16,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(text) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_STRINGLIST
-};
-
-FIELDS(url) = {
- ID3_FIELD_TYPE_LATIN1
-};
-
-FIELDS(unknown) = {
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(ZOBS) = {
- ID3_FIELD_TYPE_FRAMEID,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-# define FRAME(id) \
- sizeof(fields_##id) / sizeof(fields_##id[0]), fields_##id
-
-# define PRESERVE 0
-# define DISCARD ID3_FRAME_FLAG_FILEALTERPRESERVATION
-# define OBSOLETE (DISCARD | ID3_FRAME_FLAG_TAGALTERPRESERVATION)
-
-# define FRAMETYPE(type, id, flags, desc) \
- struct id3_frametype const id3_frametype_##type = { \
- 0, FRAME(id), flags, desc \
- }
-
-/* static frame types */
-
-FRAMETYPE(text, text, PRESERVE, "Unknown text information frame");
-FRAMETYPE(url, url, PRESERVE, "Unknown URL link frame");
-FRAMETYPE(experimental, unknown, PRESERVE, "Experimental frame");
-FRAMETYPE(unknown, unknown, PRESERVE, "Unknown frame");
-FRAMETYPE(obsolete, unknown, OBSOLETE, "Obsolete frame");
-
-#define TOTAL_KEYWORDS 84
-#define MIN_WORD_LENGTH 4
-#define MAX_WORD_LENGTH 4
-#define MIN_HASH_VALUE 7
-#define MAX_HASH_VALUE 155
-/* maximum key range = 149, duplicates = 0 */
-
-#ifdef __GNUC__
-__inline
-#else
-#ifdef __cplusplus
-inline
-#endif
-#endif
-static unsigned int
-hash (str, len)
- register const char *str;
- register unsigned int len;
-{
- static const unsigned char asso_values[] =
- {
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 43, 4, 47, 49, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 31, 53, 3, 15, 3,
- 24, 25, 10, 52, 69, 34, 23, 30, 1, 5,
- 10, 62, 20, 0, 28, 28, 22, 19, 47, 3,
- 10, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156, 156, 156, 156,
- 156, 156, 156, 156, 156, 156, 156
- };
- return asso_values[(unsigned char)str[3]+1] + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[1]] + asso_values[(unsigned char)str[0]];
-}
-
-#ifdef __GNUC__
-__inline
-#endif
-const struct id3_frametype *
-id3_frametype_lookup (str, len)
- register const char *str;
- register unsigned int len;
-{
- static const struct id3_frametype wordlist[] =
- {
-#line 282 "frametype.gperf"
- {"ENCR", FRAME(ENCR), PRESERVE, "Encryption method registration"},
-#line 292 "frametype.gperf"
- {"POPM", FRAME(POPM), PRESERVE, "Popularimeter"},
-#line 351 "frametype.gperf"
- {"WCOM", FRAME(url), PRESERVE, "Commercial information"},
-#line 298 "frametype.gperf"
- {"SEEK", FRAME(SEEK), DISCARD, "Seek frame"},
-#line 349 "frametype.gperf"
- {"USER", FRAME(USER), PRESERVE, "Terms of use"},
-#line 285 "frametype.gperf"
- {"GEOB", FRAME(GEOB), PRESERVE, "General encapsulated object"},
-#line 304 "frametype.gperf"
- {"TCOM", FRAME(text), PRESERVE, "Composer"},
-#line 281 "frametype.gperf"
- {"COMR", FRAME(COMR), PRESERVE, "Commercial frame"},
-#line 280 "frametype.gperf"
- {"COMM", FRAME(COMM), PRESERVE, "Comments"},
-#line 305 "frametype.gperf"
- {"TCON", FRAME(text), PRESERVE, "Content type"},
-#line 291 "frametype.gperf"
- {"PCNT", FRAME(PCNT), PRESERVE, "Play counter"},
-#line 293 "frametype.gperf"
- {"POSS", FRAME(POSS), DISCARD, "Position synchronisation frame"},
-#line 284 "frametype.gperf"
- {"ETCO", FRAME(ETCO), DISCARD, "Event timing codes"},
-#line 332 "frametype.gperf"
- {"TPE2", FRAME(text), PRESERVE, "Band/orchestra/accompaniment"},
-#line 301 "frametype.gperf"
- {"SYTC", FRAME(SYTC), DISCARD, "Synchronised tempo codes"},
-#line 313 "frametype.gperf"
- {"TENC", FRAME(text), DISCARD, "Encoded by"},
-#line 309 "frametype.gperf"
- {"TDOR", FRAME(text), PRESERVE, "Original release time"},
-#line 290 "frametype.gperf"
- {"OWNE", FRAME(OWNE), PRESERVE, "Ownership frame"},
-#line 277 "frametype.gperf"
- {"AENC", FRAME(AENC), DISCARD, "Audio encryption"},
-#line 307 "frametype.gperf"
- {"TDEN", FRAME(text), PRESERVE, "Encoding time"},
-#line 345 "frametype.gperf"
- {"TSSE", FRAME(text), PRESERVE, "Software/hardware and settings used for encoding"},
-#line 339 "frametype.gperf"
- {"TRSN", FRAME(text), PRESERVE, "Internet radio station name"},
-#line 300 "frametype.gperf"
- {"SYLT", FRAME(SYLT), DISCARD, "Synchronised lyric/text"},
-#line 354 "frametype.gperf"
- {"WOAR", FRAME(url), PRESERVE, "Official artist/performer webpage"},
-#line 346 "frametype.gperf"
- {"TSST", FRAME(text), PRESERVE, "Set subtitle"},
-#line 330 "frametype.gperf"
- {"TOWN", FRAME(text), PRESERVE, "File owner/licensee"},
-#line 340 "frametype.gperf"
- {"TRSO", FRAME(text), PRESERVE, "Internet radio station owner"},
-#line 322 "frametype.gperf"
- {"TLEN", FRAME(text), DISCARD, "Length"},
-#line 358 "frametype.gperf"
- {"WPUB", FRAME(url), PRESERVE, "Publishers official webpage"},
-#line 343 "frametype.gperf"
- {"TSOT", FRAME(text), PRESERVE, "Title sort order"},
-#line 327 "frametype.gperf"
- {"TOFN", FRAME(text), PRESERVE, "Original filename"},
-#line 344 "frametype.gperf"
- {"TSRC", FRAME(text), PRESERVE, "ISRC (international standard recording code)"},
-#line 324 "frametype.gperf"
- {"TMED", FRAME(text), PRESERVE, "Media type"},
-#line 297 "frametype.gperf"
- {"RVRB", FRAME(RVRB), PRESERVE, "Reverb"},
-#line 328 "frametype.gperf"
- {"TOLY", FRAME(text), PRESERVE, "Original lyricist(s)/text writer(s)"},
-#line 329 "frametype.gperf"
- {"TOPE", FRAME(text), PRESERVE, "Original artist(s)/performer(s)"},
-#line 336 "frametype.gperf"
- {"TPRO", FRAME(text), PRESERVE, "Produced notice"},
-#line 337 "frametype.gperf"
- {"TPUB", FRAME(text), PRESERVE, "Publisher"},
-#line 357 "frametype.gperf"
- {"WPAY", FRAME(url), PRESERVE, "Payment"},
-#line 335 "frametype.gperf"
- {"TPOS", FRAME(text), PRESERVE, "Part of a set"},
-#line 356 "frametype.gperf"
- {"WORS", FRAME(url), PRESERVE, "Official Internet radio station homepage"},
-#line 325 "frametype.gperf"
- {"TMOO", FRAME(text), PRESERVE, "Mood"},
-#line 338 "frametype.gperf"
- {"TRCK", FRAME(text), PRESERVE, "Track number/position in set"},
-#line 320 "frametype.gperf"
- {"TKEY", FRAME(text), PRESERVE, "Initial key"},
-#line 308 "frametype.gperf"
- {"TDLY", FRAME(text), PRESERVE, "Playlist delay"},
-#line 296 "frametype.gperf"
- {"RVA2", FRAME(RVA2), DISCARD, "Relative volume adjustment (2)"},
-#line 310 "frametype.gperf"
- {"TDRC", FRAME(text), PRESERVE, "Recording time"},
-#line 350 "frametype.gperf"
- {"USLT", FRAME(USLT), PRESERVE, "Unsynchronised lyric/text transcription"},
-#line 353 "frametype.gperf"
- {"WOAF", FRAME(url), PRESERVE, "Official audio file webpage"},
-#line 312 "frametype.gperf"
- {"TDTG", FRAME(text), PRESERVE, "Tagging time"},
-#line 299 "frametype.gperf"
- {"SIGN", FRAME(SIGN), PRESERVE, "Signature frame"},
-#line 355 "frametype.gperf"
- {"WOAS", FRAME(url), PRESERVE, "Official audio source webpage"},
-#line 331 "frametype.gperf"
- {"TPE1", FRAME(text), PRESERVE, "Lead performer(s)/soloist(s)"},
-#line 302 "frametype.gperf"
- {"TALB", FRAME(text), PRESERVE, "Album/movie/show title"},
-#line 341 "frametype.gperf"
- {"TSOA", FRAME(text), PRESERVE, "Album sort order"},
-#line 321 "frametype.gperf"
- {"TLAN", FRAME(text), PRESERVE, "Language(s)"},
-#line 333 "frametype.gperf"
- {"TPE3", FRAME(text), PRESERVE, "Conductor/performer refinement"},
-#line 352 "frametype.gperf"
- {"WCOP", FRAME(url), PRESERVE, "Copyright/legal information"},
-#line 334 "frametype.gperf"
- {"TPE4", FRAME(text), PRESERVE, "Interpreted, remixed, or otherwise modified by"},
-#line 323 "frametype.gperf"
- {"TMCL", FRAME(text), PRESERVE, "Musician credits list"},
-#line 303 "frametype.gperf"
- {"TBPM", FRAME(text), PRESERVE, "BPM (beats per minute)"},
-#line 311 "frametype.gperf"
- {"TDRL", FRAME(text), PRESERVE, "Release time"},
-#line 326 "frametype.gperf"
- {"TOAL", FRAME(text), PRESERVE, "Original album/movie/show title"},
-#line 342 "frametype.gperf"
- {"TSOP", FRAME(text), PRESERVE, "Performer sort order"},
-#line 363 "frametype.gperf"
- {"ZOBS", FRAME(ZOBS), OBSOLETE, "Obsolete frame"},
-#line 283 "frametype.gperf"
- {"EQU2", FRAME(EQU2), DISCARD, "Equalisation (2)"},
-#line 306 "frametype.gperf"
- {"TCOP", FRAME(text), PRESERVE, "Copyright message"},
-#line 287 "frametype.gperf"
- {"LINK", FRAME(LINK), PRESERVE, "Linked information"},
-#line 286 "frametype.gperf"
- {"GRID", FRAME(GRID), PRESERVE, "Group identification registration"},
-#line 294 "frametype.gperf"
- {"PRIV", FRAME(PRIV), PRESERVE, "Private frame"},
-#line 315 "frametype.gperf"
- {"TFLT", FRAME(text), PRESERVE, "File type"},
-#line 289 "frametype.gperf"
- {"MLLT", FRAME(MLLT), DISCARD, "MPEG location lookup table"},
-#line 314 "frametype.gperf"
- {"TEXT", FRAME(text), PRESERVE, "Lyricist/text writer"},
-#line 348 "frametype.gperf"
- {"UFID", FRAME(UFID), PRESERVE, "Unique file identifier"},
-#line 278 "frametype.gperf"
- {"APIC", FRAME(APIC), PRESERVE, "Attached picture"},
-#line 279 "frametype.gperf"
- {"ASPI", FRAME(ASPI), DISCARD, "Audio seek point index"},
-#line 318 "frametype.gperf"
- {"TIT2", FRAME(text), PRESERVE, "Title/songname/content description"},
-#line 359 "frametype.gperf"
- {"WXXX", FRAME(WXXX), PRESERVE, "User defined URL link frame"},
-#line 288 "frametype.gperf"
- {"MCDI", FRAME(MCDI), PRESERVE, "Music CD identifier"},
-#line 316 "frametype.gperf"
- {"TIPL", FRAME(text), PRESERVE, "Involved people list"},
-#line 347 "frametype.gperf"
- {"TXXX", FRAME(TXXX), PRESERVE, "User defined text information frame"},
-#line 295 "frametype.gperf"
- {"RBUF", FRAME(RBUF), PRESERVE, "Recommended buffer size"},
-#line 317 "frametype.gperf"
- {"TIT1", FRAME(text), PRESERVE, "Content group description"},
-#line 319 "frametype.gperf"
- {"TIT3", FRAME(text), PRESERVE, "Subtitle/description refinement"}
- };
-
- static const short lookup[] =
- {
- -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1,
- 2, 3, -1, 4, -1, -1, -1, -1, 5, 6, 7, 8, -1, 9,
- 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
- 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
- 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
- 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
- 66, 67, 68, 69, -1, 70, 71, -1, 72, 73, 74, -1, 75, -1,
- 76, -1, -1, -1, 77, 78, -1, -1, 79, -1, -1, -1, -1, 80,
- 81, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 82, -1, -1,
- -1, 83
- };
-
- if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
- {
- register int key = hash (str, len);
-
- if (key <= MAX_HASH_VALUE && key >= 0)
- {
- register int index = lookup[key];
-
- if (index >= 0)
- {
- register const char *s = wordlist[index].id;
-
- if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
- return &wordlist[index];
- }
- }
- }
- return 0;
-}
diff --git a/src/libid3tag/frametype.gperf b/src/libid3tag/frametype.gperf
deleted file mode 100644
index 1c8ff2e..0000000
--- a/src/libid3tag/frametype.gperf
+++ /dev/null
@@ -1,363 +0,0 @@
-%{
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: frametype.gperf,v 1.7 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <string.h>
-
-# include "id3tag.h"
-# include "frametype.h"
-
-# define FIELDS(id) static enum id3_field_type const fields_##id[]
-
-/* frame field descriptions */
-
-FIELDS(UFID) = {
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(TXXX) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_STRING
-};
-
-FIELDS(WXXX) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_LATIN1
-};
-
-FIELDS(MCDI) = {
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(ETCO) = {
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(MLLT) = {
- ID3_FIELD_TYPE_INT16,
- ID3_FIELD_TYPE_INT24,
- ID3_FIELD_TYPE_INT24,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(SYTC) = {
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(USLT) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LANGUAGE,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_STRINGFULL
-};
-
-FIELDS(SYLT) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LANGUAGE,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(COMM) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LANGUAGE,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_STRINGFULL
-};
-
-FIELDS(RVA2) = {
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(EQU2) = {
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(RVRB) = {
- ID3_FIELD_TYPE_INT16,
- ID3_FIELD_TYPE_INT16,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT8
-};
-
-FIELDS(APIC) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(GEOB) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(PCNT) = {
- ID3_FIELD_TYPE_INT32PLUS
-};
-
-FIELDS(POPM) = {
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT32PLUS
-};
-
-FIELDS(RBUF) = {
- ID3_FIELD_TYPE_INT24,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT32
-};
-
-FIELDS(AENC) = {
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_INT16,
- ID3_FIELD_TYPE_INT16,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(LINK) = {
- ID3_FIELD_TYPE_FRAMEID,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_LATIN1LIST
-};
-
-FIELDS(POSS) = {
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(USER) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LANGUAGE,
- ID3_FIELD_TYPE_STRING
-};
-
-FIELDS(OWNE) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_DATE,
- ID3_FIELD_TYPE_STRING
-};
-
-FIELDS(COMR) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_DATE,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(ENCR) = {
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(GRID) = {
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(PRIV) = {
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(SIGN) = {
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(SEEK) = {
- ID3_FIELD_TYPE_INT32
-};
-
-FIELDS(ASPI) = {
- ID3_FIELD_TYPE_INT32,
- ID3_FIELD_TYPE_INT32,
- ID3_FIELD_TYPE_INT16,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(text) = {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_STRINGLIST
-};
-
-FIELDS(url) = {
- ID3_FIELD_TYPE_LATIN1
-};
-
-FIELDS(unknown) = {
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-FIELDS(ZOBS) = {
- ID3_FIELD_TYPE_FRAMEID,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-# define FRAME(id) \
- sizeof(fields_##id) / sizeof(fields_##id[0]), fields_##id
-
-# define PRESERVE 0
-# define DISCARD ID3_FRAME_FLAG_FILEALTERPRESERVATION
-# define OBSOLETE (DISCARD | ID3_FRAME_FLAG_TAGALTERPRESERVATION)
-
-# define FRAMETYPE(type, id, flags, desc) \
- struct id3_frametype const id3_frametype_##type = { \
- 0, FRAME(id), flags, desc \
- }
-
-/* static frame types */
-
-FRAMETYPE(text, text, PRESERVE, "Unknown text information frame");
-FRAMETYPE(url, url, PRESERVE, "Unknown URL link frame");
-FRAMETYPE(experimental, unknown, PRESERVE, "Experimental frame");
-FRAMETYPE(unknown, unknown, PRESERVE, "Unknown frame");
-FRAMETYPE(obsolete, unknown, OBSOLETE, "Obsolete frame");
-%}
-struct id3_frametype;
-%%
-#
-# ID3v2.4 frames
-#
-AENC, FRAME(AENC), DISCARD, "Audio encryption"
-APIC, FRAME(APIC), PRESERVE, "Attached picture"
-ASPI, FRAME(ASPI), DISCARD, "Audio seek point index"
-COMM, FRAME(COMM), PRESERVE, "Comments"
-COMR, FRAME(COMR), PRESERVE, "Commercial frame"
-ENCR, FRAME(ENCR), PRESERVE, "Encryption method registration"
-EQU2, FRAME(EQU2), DISCARD, "Equalisation (2)"
-ETCO, FRAME(ETCO), DISCARD, "Event timing codes"
-GEOB, FRAME(GEOB), PRESERVE, "General encapsulated object"
-GRID, FRAME(GRID), PRESERVE, "Group identification registration"
-LINK, FRAME(LINK), PRESERVE, "Linked information"
-MCDI, FRAME(MCDI), PRESERVE, "Music CD identifier"
-MLLT, FRAME(MLLT), DISCARD, "MPEG location lookup table"
-OWNE, FRAME(OWNE), PRESERVE, "Ownership frame"
-PCNT, FRAME(PCNT), PRESERVE, "Play counter"
-POPM, FRAME(POPM), PRESERVE, "Popularimeter"
-POSS, FRAME(POSS), DISCARD, "Position synchronisation frame"
-PRIV, FRAME(PRIV), PRESERVE, "Private frame"
-RBUF, FRAME(RBUF), PRESERVE, "Recommended buffer size"
-RVA2, FRAME(RVA2), DISCARD, "Relative volume adjustment (2)"
-RVRB, FRAME(RVRB), PRESERVE, "Reverb"
-SEEK, FRAME(SEEK), DISCARD, "Seek frame"
-SIGN, FRAME(SIGN), PRESERVE, "Signature frame"
-SYLT, FRAME(SYLT), DISCARD, "Synchronised lyric/text"
-SYTC, FRAME(SYTC), DISCARD, "Synchronised tempo codes"
-TALB, FRAME(text), PRESERVE, "Album/movie/show title"
-TBPM, FRAME(text), PRESERVE, "BPM (beats per minute)"
-TCOM, FRAME(text), PRESERVE, "Composer"
-TCON, FRAME(text), PRESERVE, "Content type"
-TCOP, FRAME(text), PRESERVE, "Copyright message"
-TDEN, FRAME(text), PRESERVE, "Encoding time"
-TDLY, FRAME(text), PRESERVE, "Playlist delay"
-TDOR, FRAME(text), PRESERVE, "Original release time"
-TDRC, FRAME(text), PRESERVE, "Recording time"
-TDRL, FRAME(text), PRESERVE, "Release time"
-TDTG, FRAME(text), PRESERVE, "Tagging time"
-TENC, FRAME(text), DISCARD, "Encoded by"
-TEXT, FRAME(text), PRESERVE, "Lyricist/text writer"
-TFLT, FRAME(text), PRESERVE, "File type"
-TIPL, FRAME(text), PRESERVE, "Involved people list"
-TIT1, FRAME(text), PRESERVE, "Content group description"
-TIT2, FRAME(text), PRESERVE, "Title/songname/content description"
-TIT3, FRAME(text), PRESERVE, "Subtitle/description refinement"
-TKEY, FRAME(text), PRESERVE, "Initial key"
-TLAN, FRAME(text), PRESERVE, "Language(s)"
-TLEN, FRAME(text), DISCARD, "Length"
-TMCL, FRAME(text), PRESERVE, "Musician credits list"
-TMED, FRAME(text), PRESERVE, "Media type"
-TMOO, FRAME(text), PRESERVE, "Mood"
-TOAL, FRAME(text), PRESERVE, "Original album/movie/show title"
-TOFN, FRAME(text), PRESERVE, "Original filename"
-TOLY, FRAME(text), PRESERVE, "Original lyricist(s)/text writer(s)"
-TOPE, FRAME(text), PRESERVE, "Original artist(s)/performer(s)"
-TOWN, FRAME(text), PRESERVE, "File owner/licensee"
-TPE1, FRAME(text), PRESERVE, "Lead performer(s)/soloist(s)"
-TPE2, FRAME(text), PRESERVE, "Band/orchestra/accompaniment"
-TPE3, FRAME(text), PRESERVE, "Conductor/performer refinement"
-TPE4, FRAME(text), PRESERVE, "Interpreted, remixed, or otherwise modified by"
-TPOS, FRAME(text), PRESERVE, "Part of a set"
-TPRO, FRAME(text), PRESERVE, "Produced notice"
-TPUB, FRAME(text), PRESERVE, "Publisher"
-TRCK, FRAME(text), PRESERVE, "Track number/position in set"
-TRSN, FRAME(text), PRESERVE, "Internet radio station name"
-TRSO, FRAME(text), PRESERVE, "Internet radio station owner"
-TSOA, FRAME(text), PRESERVE, "Album sort order"
-TSOP, FRAME(text), PRESERVE, "Performer sort order"
-TSOT, FRAME(text), PRESERVE, "Title sort order"
-TSRC, FRAME(text), PRESERVE, "ISRC (international standard recording code)"
-TSSE, FRAME(text), PRESERVE, "Software/hardware and settings used for encoding"
-TSST, FRAME(text), PRESERVE, "Set subtitle"
-TXXX, FRAME(TXXX), PRESERVE, "User defined text information frame"
-UFID, FRAME(UFID), PRESERVE, "Unique file identifier"
-USER, FRAME(USER), PRESERVE, "Terms of use"
-USLT, FRAME(USLT), PRESERVE, "Unsynchronised lyric/text transcription"
-WCOM, FRAME(url), PRESERVE, "Commercial information"
-WCOP, FRAME(url), PRESERVE, "Copyright/legal information"
-WOAF, FRAME(url), PRESERVE, "Official audio file webpage"
-WOAR, FRAME(url), PRESERVE, "Official artist/performer webpage"
-WOAS, FRAME(url), PRESERVE, "Official audio source webpage"
-WORS, FRAME(url), PRESERVE, "Official Internet radio station homepage"
-WPAY, FRAME(url), PRESERVE, "Payment"
-WPUB, FRAME(url), PRESERVE, "Publishers official webpage"
-WXXX, FRAME(WXXX), PRESERVE, "User defined URL link frame"
-#
-# Special frames
-#
-ZOBS, FRAME(ZOBS), OBSOLETE, "Obsolete frame"
diff --git a/src/libid3tag/frametype.h b/src/libid3tag/frametype.h
deleted file mode 100644
index dd064b2..0000000
--- a/src/libid3tag/frametype.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: frametype.h,v 1.7 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_FRAMETYPE_H
-# define LIBID3TAG_FRAMETYPE_H
-
-struct id3_frametype {
- char const *id;
- unsigned int nfields;
- enum id3_field_type const *fields;
- int defaultflags;
- char const *description;
-};
-
-extern struct id3_frametype const id3_frametype_text;
-extern struct id3_frametype const id3_frametype_url;
-extern struct id3_frametype const id3_frametype_experimental;
-extern struct id3_frametype const id3_frametype_unknown;
-extern struct id3_frametype const id3_frametype_obsolete;
-
-struct id3_frametype const *id3_frametype_lookup(register char const *,
- register unsigned int);
-
-# endif
diff --git a/src/libid3tag/genre.c b/src/libid3tag/genre.c
deleted file mode 100644
index 9721101..0000000
--- a/src/libid3tag/genre.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: genre.c,v 1.8 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include "id3tag.h"
-# include "ucs4.h"
-
-/* genres are stored in ucs4 format */
-# include "genre.dat"
-
-# define NGENRES (sizeof(genre_table) / sizeof(genre_table[0]))
-
-/*
- * NAME: genre->index()
- * DESCRIPTION: return an ID3v1 genre string indexed by number
- */
-id3_ucs4_t const *id3_genre_index(unsigned int index)
-{
- return (index < NGENRES) ? genre_table[index] : 0;
-}
-
-/*
- * NAME: genre->name()
- * DESCRIPTION: translate an ID3v2 genre number/keyword to its full name
- */
-id3_ucs4_t const *id3_genre_name(id3_ucs4_t const *string)
-{
- id3_ucs4_t *ptr;
- static id3_ucs4_t const genre_remix[] = { 'R', 'e', 'm', 'i', 'x', 0 };
- static id3_ucs4_t const genre_cover[] = { 'C', 'o', 'v', 'e', 'r', 0 };
- unsigned long number;
-
- if (string == 0 || *string == 0)
- return id3_ucs4_empty;
-
- if (string[0] == 'R' && string[1] == 'X' && string[2] == 0)
- return genre_remix;
- if (string[0] == 'C' && string[1] == 'R' && string[2] == 0)
- return genre_cover;
-
- for (ptr = (id3_ucs4_t *)string; *ptr; ++ptr) {
- if (*ptr < '0' || *ptr > '9')
- return string;
- }
-
- number = id3_ucs4_getnumber(string);
-
- return (number < NGENRES) ? genre_table[number] : string;
-}
-
-/*
- * NAME: translate()
- * DESCRIPTION: return a canonicalized character for testing genre equivalence
- */
-static
-id3_ucs4_t translate(id3_ucs4_t ch)
-{
- if (ch) {
- if (ch >= 'A' && ch <= 'Z')
- ch += 'a' - 'A';
-
- if (ch < 'a' || ch > 'z')
- ch = ID3_UCS4_REPLACEMENTCHAR;
- }
-
- return ch;
-}
-
-/*
- * NAME: compare()
- * DESCRIPTION: test two ucs4 genre strings for equivalence
- */
-static
-int compare(id3_ucs4_t const *str1, id3_ucs4_t const *str2)
-{
- id3_ucs4_t c1, c2;
-
- if (str1 == str2)
- return 1;
-
- do {
- do
- c1 = translate(*str1++);
- while (c1 == ID3_UCS4_REPLACEMENTCHAR);
-
- do
- c2 = translate(*str2++);
- while (c2 == ID3_UCS4_REPLACEMENTCHAR);
- }
- while (c1 && c1 == c2);
-
- return c1 == c2;
-}
-
-/*
- * NAME: genre->number()
- * DESCRIPTION: translate an ID3v2 genre name/number to its ID3v1 index number
- */
-int id3_genre_number(id3_ucs4_t const *string)
-{
- id3_ucs4_t const *ptr;
- int i;
-
- if (string == 0 || *string == 0)
- return -1;
-
- for (ptr = string; *ptr; ++ptr) {
- if (*ptr < '0' || *ptr > '9')
- break;
- }
-
- if (*ptr == 0) {
- unsigned long number;
-
- number = id3_ucs4_getnumber(string);
-
- return (number <= 0xff) ? number : -1;
- }
-
- for (i = 0; i < NGENRES; ++i) {
- if (compare(string, genre_table[i]))
- return i;
- }
-
- /* no equivalent */
-
- return -1;
-}
diff --git a/src/libid3tag/genre.dat b/src/libid3tag/genre.dat
deleted file mode 100644
index 17acab5..0000000
--- a/src/libid3tag/genre.dat
+++ /dev/null
@@ -1,480 +0,0 @@
-/* Automatically generated from genre.dat.in */
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * Id: genre.dat.in,v 1.7 2004/01/23 09:41:32 rob Exp
- */
-
-/*
- * These are the ID3 genre names, taken as a combination of names from ID3v1
- * (listed in Appendix A of the ID3 tag version 2.4.0 informal standard) and
- * the extensions made by Winamp as of version 2.80.
- */
-
-/* ID3v1 names (0-79) */
-
-static id3_ucs4_t const genre_BLUES[] =
- { 'B', 'l', 'u', 'e', 's', 0 };
-static id3_ucs4_t const genre_CLASSIC_ROCK[] =
- { 'C', 'l', 'a', 's', 's', 'i', 'c', ' ', 'R', 'o', 'c', 'k', 0 };
-static id3_ucs4_t const genre_COUNTRY[] =
- { 'C', 'o', 'u', 'n', 't', 'r', 'y', 0 };
-static id3_ucs4_t const genre_DANCE[] =
- { 'D', 'a', 'n', 'c', 'e', 0 };
-static id3_ucs4_t const genre_DISCO[] =
- { 'D', 'i', 's', 'c', 'o', 0 };
-static id3_ucs4_t const genre_FUNK[] =
- { 'F', 'u', 'n', 'k', 0 };
-static id3_ucs4_t const genre_GRUNGE[] =
- { 'G', 'r', 'u', 'n', 'g', 'e', 0 };
-static id3_ucs4_t const genre_HIP_HOP[] =
- { 'H', 'i', 'p', '-', 'H', 'o', 'p', 0 };
-static id3_ucs4_t const genre_JAZZ[] =
- { 'J', 'a', 'z', 'z', 0 };
-static id3_ucs4_t const genre_METAL[] =
- { 'M', 'e', 't', 'a', 'l', 0 };
-static id3_ucs4_t const genre_NEW_AGE[] =
- { 'N', 'e', 'w', ' ', 'A', 'g', 'e', 0 };
-static id3_ucs4_t const genre_OLDIES[] =
- { 'O', 'l', 'd', 'i', 'e', 's', 0 };
-static id3_ucs4_t const genre_OTHER[] =
- { 'O', 't', 'h', 'e', 'r', 0 };
-static id3_ucs4_t const genre_POP[] =
- { 'P', 'o', 'p', 0 };
-static id3_ucs4_t const genre_R_B[] =
- { 'R', '&', 'B', 0 };
-static id3_ucs4_t const genre_RAP[] =
- { 'R', 'a', 'p', 0 };
-static id3_ucs4_t const genre_REGGAE[] =
- { 'R', 'e', 'g', 'g', 'a', 'e', 0 };
-static id3_ucs4_t const genre_ROCK[] =
- { 'R', 'o', 'c', 'k', 0 };
-static id3_ucs4_t const genre_TECHNO[] =
- { 'T', 'e', 'c', 'h', 'n', 'o', 0 };
-static id3_ucs4_t const genre_INDUSTRIAL[] =
- { 'I', 'n', 'd', 'u', 's', 't', 'r', 'i', 'a', 'l', 0 };
-static id3_ucs4_t const genre_ALTERNATIVE[] =
- { 'A', 'l', 't', 'e', 'r', 'n', 'a', 't', 'i', 'v', 'e', 0 };
-static id3_ucs4_t const genre_SKA[] =
- { 'S', 'k', 'a', 0 };
-static id3_ucs4_t const genre_DEATH_METAL[] =
- { 'D', 'e', 'a', 't', 'h', ' ', 'M', 'e', 't', 'a', 'l', 0 };
-static id3_ucs4_t const genre_PRANKS[] =
- { 'P', 'r', 'a', 'n', 'k', 's', 0 };
-static id3_ucs4_t const genre_SOUNDTRACK[] =
- { 'S', 'o', 'u', 'n', 'd', 't', 'r', 'a', 'c', 'k', 0 };
-static id3_ucs4_t const genre_EURO_TECHNO[] =
- { 'E', 'u', 'r', 'o', '-', 'T', 'e', 'c', 'h', 'n', 'o', 0 };
-static id3_ucs4_t const genre_AMBIENT[] =
- { 'A', 'm', 'b', 'i', 'e', 'n', 't', 0 };
-static id3_ucs4_t const genre_TRIP_HOP[] =
- { 'T', 'r', 'i', 'p', '-', 'H', 'o', 'p', 0 };
-static id3_ucs4_t const genre_VOCAL[] =
- { 'V', 'o', 'c', 'a', 'l', 0 };
-static id3_ucs4_t const genre_JAZZ_FUNK[] =
- { 'J', 'a', 'z', 'z', '+', 'F', 'u', 'n', 'k', 0 };
-static id3_ucs4_t const genre_FUSION[] =
- { 'F', 'u', 's', 'i', 'o', 'n', 0 };
-static id3_ucs4_t const genre_TRANCE[] =
- { 'T', 'r', 'a', 'n', 'c', 'e', 0 };
-static id3_ucs4_t const genre_CLASSICAL[] =
- { 'C', 'l', 'a', 's', 's', 'i', 'c', 'a', 'l', 0 };
-static id3_ucs4_t const genre_INSTRUMENTAL[] =
- { 'I', 'n', 's', 't', 'r', 'u', 'm', 'e', 'n', 't', 'a', 'l', 0 };
-static id3_ucs4_t const genre_ACID[] =
- { 'A', 'c', 'i', 'd', 0 };
-static id3_ucs4_t const genre_HOUSE[] =
- { 'H', 'o', 'u', 's', 'e', 0 };
-static id3_ucs4_t const genre_GAME[] =
- { 'G', 'a', 'm', 'e', 0 };
-static id3_ucs4_t const genre_SOUND_CLIP[] =
- { 'S', 'o', 'u', 'n', 'd', ' ', 'C', 'l', 'i', 'p', 0 };
-static id3_ucs4_t const genre_GOSPEL[] =
- { 'G', 'o', 's', 'p', 'e', 'l', 0 };
-static id3_ucs4_t const genre_NOISE[] =
- { 'N', 'o', 'i', 's', 'e', 0 };
-static id3_ucs4_t const genre_ALTERNROCK[] =
- { 'A', 'l', 't', 'e', 'r', 'n', 'R', 'o', 'c', 'k', 0 };
-static id3_ucs4_t const genre_BASS[] =
- { 'B', 'a', 's', 's', 0 };
-static id3_ucs4_t const genre_SOUL[] =
- { 'S', 'o', 'u', 'l', 0 };
-static id3_ucs4_t const genre_PUNK[] =
- { 'P', 'u', 'n', 'k', 0 };
-static id3_ucs4_t const genre_SPACE[] =
- { 'S', 'p', 'a', 'c', 'e', 0 };
-static id3_ucs4_t const genre_MEDITATIVE[] =
- { 'M', 'e', 'd', 'i', 't', 'a', 't', 'i', 'v', 'e', 0 };
-static id3_ucs4_t const genre_INSTRUMENTAL_POP[] =
- { 'I', 'n', 's', 't', 'r', 'u', 'm', 'e', 'n', 't', 'a', 'l', ' ', 'P', 'o', 'p', 0 };
-static id3_ucs4_t const genre_INSTRUMENTAL_ROCK[] =
- { 'I', 'n', 's', 't', 'r', 'u', 'm', 'e', 'n', 't', 'a', 'l', ' ', 'R', 'o', 'c', 'k', 0 };
-static id3_ucs4_t const genre_ETHNIC[] =
- { 'E', 't', 'h', 'n', 'i', 'c', 0 };
-static id3_ucs4_t const genre_GOTHIC[] =
- { 'G', 'o', 't', 'h', 'i', 'c', 0 };
-static id3_ucs4_t const genre_DARKWAVE[] =
- { 'D', 'a', 'r', 'k', 'w', 'a', 'v', 'e', 0 };
-static id3_ucs4_t const genre_TECHNO_INDUSTRIAL[] =
- { 'T', 'e', 'c', 'h', 'n', 'o', '-', 'I', 'n', 'd', 'u', 's', 't', 'r', 'i', 'a', 'l', 0 };
-static id3_ucs4_t const genre_ELECTRONIC[] =
- { 'E', 'l', 'e', 'c', 't', 'r', 'o', 'n', 'i', 'c', 0 };
-static id3_ucs4_t const genre_POP_FOLK[] =
- { 'P', 'o', 'p', '-', 'F', 'o', 'l', 'k', 0 };
-static id3_ucs4_t const genre_EURODANCE[] =
- { 'E', 'u', 'r', 'o', 'd', 'a', 'n', 'c', 'e', 0 };
-static id3_ucs4_t const genre_DREAM[] =
- { 'D', 'r', 'e', 'a', 'm', 0 };
-static id3_ucs4_t const genre_SOUTHERN_ROCK[] =
- { 'S', 'o', 'u', 't', 'h', 'e', 'r', 'n', ' ', 'R', 'o', 'c', 'k', 0 };
-static id3_ucs4_t const genre_COMEDY[] =
- { 'C', 'o', 'm', 'e', 'd', 'y', 0 };
-static id3_ucs4_t const genre_CULT[] =
- { 'C', 'u', 'l', 't', 0 };
-static id3_ucs4_t const genre_GANGSTA[] =
- { 'G', 'a', 'n', 'g', 's', 't', 'a', 0 };
-static id3_ucs4_t const genre_TOP_40[] =
- { 'T', 'o', 'p', ' ', '4', '0', 0 };
-static id3_ucs4_t const genre_CHRISTIAN_RAP[] =
- { 'C', 'h', 'r', 'i', 's', 't', 'i', 'a', 'n', ' ', 'R', 'a', 'p', 0 };
-static id3_ucs4_t const genre_POP_FUNK[] =
- { 'P', 'o', 'p', '/', 'F', 'u', 'n', 'k', 0 };
-static id3_ucs4_t const genre_JUNGLE[] =
- { 'J', 'u', 'n', 'g', 'l', 'e', 0 };
-static id3_ucs4_t const genre_NATIVE_AMERICAN[] =
- { 'N', 'a', 't', 'i', 'v', 'e', ' ', 'A', 'm', 'e', 'r', 'i', 'c', 'a', 'n', 0 };
-static id3_ucs4_t const genre_CABARET[] =
- { 'C', 'a', 'b', 'a', 'r', 'e', 't', 0 };
-static id3_ucs4_t const genre_NEW_WAVE[] =
- { 'N', 'e', 'w', ' ', 'W', 'a', 'v', 'e', 0 };
-static id3_ucs4_t const genre_PSYCHEDELIC[] =
- { 'P', 's', 'y', 'c', 'h', 'e', 'd', 'e', 'l', 'i', 'c', 0 };
-static id3_ucs4_t const genre_RAVE[] =
- { 'R', 'a', 'v', 'e', 0 };
-static id3_ucs4_t const genre_SHOWTUNES[] =
- { 'S', 'h', 'o', 'w', 't', 'u', 'n', 'e', 's', 0 };
-static id3_ucs4_t const genre_TRAILER[] =
- { 'T', 'r', 'a', 'i', 'l', 'e', 'r', 0 };
-static id3_ucs4_t const genre_LO_FI[] =
- { 'L', 'o', '-', 'F', 'i', 0 };
-static id3_ucs4_t const genre_TRIBAL[] =
- { 'T', 'r', 'i', 'b', 'a', 'l', 0 };
-static id3_ucs4_t const genre_ACID_PUNK[] =
- { 'A', 'c', 'i', 'd', ' ', 'P', 'u', 'n', 'k', 0 };
-static id3_ucs4_t const genre_ACID_JAZZ[] =
- { 'A', 'c', 'i', 'd', ' ', 'J', 'a', 'z', 'z', 0 };
-static id3_ucs4_t const genre_POLKA[] =
- { 'P', 'o', 'l', 'k', 'a', 0 };
-static id3_ucs4_t const genre_RETRO[] =
- { 'R', 'e', 't', 'r', 'o', 0 };
-static id3_ucs4_t const genre_MUSICAL[] =
- { 'M', 'u', 's', 'i', 'c', 'a', 'l', 0 };
-static id3_ucs4_t const genre_ROCK___ROLL[] =
- { 'R', 'o', 'c', 'k', ' ', '&', ' ', 'R', 'o', 'l', 'l', 0 };
-static id3_ucs4_t const genre_HARD_ROCK[] =
- { 'H', 'a', 'r', 'd', ' ', 'R', 'o', 'c', 'k', 0 };
-
-/* Winamp extensions (80-147) */
-
-static id3_ucs4_t const genre_FOLK[] =
- { 'F', 'o', 'l', 'k', 0 };
-static id3_ucs4_t const genre_FOLK_ROCK[] =
- { 'F', 'o', 'l', 'k', '/', 'R', 'o', 'c', 'k', 0 };
-static id3_ucs4_t const genre_NATIONAL_FOLK[] =
- { 'N', 'a', 't', 'i', 'o', 'n', 'a', 'l', ' ', 'F', 'o', 'l', 'k', 0 };
-static id3_ucs4_t const genre_SWING[] =
- { 'S', 'w', 'i', 'n', 'g', 0 };
-static id3_ucs4_t const genre_FAST_FUSION[] =
- { 'F', 'a', 's', 't', '-', 'F', 'u', 's', 'i', 'o', 'n', 0 };
-static id3_ucs4_t const genre_BEBOB[] =
- { 'B', 'e', 'b', 'o', 'b', 0 };
-static id3_ucs4_t const genre_LATIN[] =
- { 'L', 'a', 't', 'i', 'n', 0 };
-static id3_ucs4_t const genre_REVIVAL[] =
- { 'R', 'e', 'v', 'i', 'v', 'a', 'l', 0 };
-static id3_ucs4_t const genre_CELTIC[] =
- { 'C', 'e', 'l', 't', 'i', 'c', 0 };
-static id3_ucs4_t const genre_BLUEGRASS[] =
- { 'B', 'l', 'u', 'e', 'g', 'r', 'a', 's', 's', 0 };
-static id3_ucs4_t const genre_AVANTGARDE[] =
- { 'A', 'v', 'a', 'n', 't', 'g', 'a', 'r', 'd', 'e', 0 };
-static id3_ucs4_t const genre_GOTHIC_ROCK[] =
- { 'G', 'o', 't', 'h', 'i', 'c', ' ', 'R', 'o', 'c', 'k', 0 };
-static id3_ucs4_t const genre_PROGRESSIVE_ROCK[] =
- { 'P', 'r', 'o', 'g', 'r', 'e', 's', 's', 'i', 'v', 'e', ' ', 'R', 'o', 'c', 'k', 0 };
-static id3_ucs4_t const genre_PSYCHEDELIC_ROCK[] =
- { 'P', 's', 'y', 'c', 'h', 'e', 'd', 'e', 'l', 'i', 'c', ' ', 'R', 'o', 'c', 'k', 0 };
-static id3_ucs4_t const genre_SYMPHONIC_ROCK[] =
- { 'S', 'y', 'm', 'p', 'h', 'o', 'n', 'i', 'c', ' ', 'R', 'o', 'c', 'k', 0 };
-static id3_ucs4_t const genre_SLOW_ROCK[] =
- { 'S', 'l', 'o', 'w', ' ', 'R', 'o', 'c', 'k', 0 };
-static id3_ucs4_t const genre_BIG_BAND[] =
- { 'B', 'i', 'g', ' ', 'B', 'a', 'n', 'd', 0 };
-static id3_ucs4_t const genre_CHORUS[] =
- { 'C', 'h', 'o', 'r', 'u', 's', 0 };
-static id3_ucs4_t const genre_EASY_LISTENING[] =
- { 'E', 'a', 's', 'y', ' ', 'L', 'i', 's', 't', 'e', 'n', 'i', 'n', 'g', 0 };
-static id3_ucs4_t const genre_ACOUSTIC[] =
- { 'A', 'c', 'o', 'u', 's', 't', 'i', 'c', 0 };
-static id3_ucs4_t const genre_HUMOUR[] =
- { 'H', 'u', 'm', 'o', 'u', 'r', 0 };
-static id3_ucs4_t const genre_SPEECH[] =
- { 'S', 'p', 'e', 'e', 'c', 'h', 0 };
-static id3_ucs4_t const genre_CHANSON[] =
- { 'C', 'h', 'a', 'n', 's', 'o', 'n', 0 };
-static id3_ucs4_t const genre_OPERA[] =
- { 'O', 'p', 'e', 'r', 'a', 0 };
-static id3_ucs4_t const genre_CHAMBER_MUSIC[] =
- { 'C', 'h', 'a', 'm', 'b', 'e', 'r', ' ', 'M', 'u', 's', 'i', 'c', 0 };
-static id3_ucs4_t const genre_SONATA[] =
- { 'S', 'o', 'n', 'a', 't', 'a', 0 };
-static id3_ucs4_t const genre_SYMPHONY[] =
- { 'S', 'y', 'm', 'p', 'h', 'o', 'n', 'y', 0 };
-static id3_ucs4_t const genre_BOOTY_BASS[] =
- { 'B', 'o', 'o', 't', 'y', ' ', 'B', 'a', 's', 's', 0 };
-static id3_ucs4_t const genre_PRIMUS[] =
- { 'P', 'r', 'i', 'm', 'u', 's', 0 };
-static id3_ucs4_t const genre_PORN_GROOVE[] =
- { 'P', 'o', 'r', 'n', ' ', 'G', 'r', 'o', 'o', 'v', 'e', 0 };
-static id3_ucs4_t const genre_SATIRE[] =
- { 'S', 'a', 't', 'i', 'r', 'e', 0 };
-static id3_ucs4_t const genre_SLOW_JAM[] =
- { 'S', 'l', 'o', 'w', ' ', 'J', 'a', 'm', 0 };
-static id3_ucs4_t const genre_CLUB[] =
- { 'C', 'l', 'u', 'b', 0 };
-static id3_ucs4_t const genre_TANGO[] =
- { 'T', 'a', 'n', 'g', 'o', 0 };
-static id3_ucs4_t const genre_SAMBA[] =
- { 'S', 'a', 'm', 'b', 'a', 0 };
-static id3_ucs4_t const genre_FOLKLORE[] =
- { 'F', 'o', 'l', 'k', 'l', 'o', 'r', 'e', 0 };
-static id3_ucs4_t const genre_BALLAD[] =
- { 'B', 'a', 'l', 'l', 'a', 'd', 0 };
-static id3_ucs4_t const genre_POWER_BALLAD[] =
- { 'P', 'o', 'w', 'e', 'r', ' ', 'B', 'a', 'l', 'l', 'a', 'd', 0 };
-static id3_ucs4_t const genre_RHYTHMIC_SOUL[] =
- { 'R', 'h', 'y', 't', 'h', 'm', 'i', 'c', ' ', 'S', 'o', 'u', 'l', 0 };
-static id3_ucs4_t const genre_FREESTYLE[] =
- { 'F', 'r', 'e', 'e', 's', 't', 'y', 'l', 'e', 0 };
-static id3_ucs4_t const genre_DUET[] =
- { 'D', 'u', 'e', 't', 0 };
-static id3_ucs4_t const genre_PUNK_ROCK[] =
- { 'P', 'u', 'n', 'k', ' ', 'R', 'o', 'c', 'k', 0 };
-static id3_ucs4_t const genre_DRUM_SOLO[] =
- { 'D', 'r', 'u', 'm', ' ', 'S', 'o', 'l', 'o', 0 };
-static id3_ucs4_t const genre_A_CAPPELLA[] =
- { 'A', ' ', 'C', 'a', 'p', 'p', 'e', 'l', 'l', 'a', 0 };
-static id3_ucs4_t const genre_EURO_HOUSE[] =
- { 'E', 'u', 'r', 'o', '-', 'H', 'o', 'u', 's', 'e', 0 };
-static id3_ucs4_t const genre_DANCE_HALL[] =
- { 'D', 'a', 'n', 'c', 'e', ' ', 'H', 'a', 'l', 'l', 0 };
-static id3_ucs4_t const genre_GOA[] =
- { 'G', 'o', 'a', 0 };
-static id3_ucs4_t const genre_DRUM___BASS[] =
- { 'D', 'r', 'u', 'm', ' ', '&', ' ', 'B', 'a', 's', 's', 0 };
-static id3_ucs4_t const genre_CLUB_HOUSE[] =
- { 'C', 'l', 'u', 'b', '-', 'H', 'o', 'u', 's', 'e', 0 };
-static id3_ucs4_t const genre_HARDCORE[] =
- { 'H', 'a', 'r', 'd', 'c', 'o', 'r', 'e', 0 };
-static id3_ucs4_t const genre_TERROR[] =
- { 'T', 'e', 'r', 'r', 'o', 'r', 0 };
-static id3_ucs4_t const genre_INDIE[] =
- { 'I', 'n', 'd', 'i', 'e', 0 };
-static id3_ucs4_t const genre_BRITPOP[] =
- { 'B', 'r', 'i', 't', 'P', 'o', 'p', 0 };
-static id3_ucs4_t const genre_NEGERPUNK[] =
- { 'N', 'e', 'g', 'e', 'r', 'p', 'u', 'n', 'k', 0 };
-static id3_ucs4_t const genre_POLSK_PUNK[] =
- { 'P', 'o', 'l', 's', 'k', ' ', 'P', 'u', 'n', 'k', 0 };
-static id3_ucs4_t const genre_BEAT[] =
- { 'B', 'e', 'a', 't', 0 };
-static id3_ucs4_t const genre_CHRISTIAN_GANGSTA_RAP[] =
- { 'C', 'h', 'r', 'i', 's', 't', 'i', 'a', 'n', ' ', 'G', 'a', 'n', 'g', 's', 't', 'a', ' ', 'R', 'a', 'p', 0 };
-static id3_ucs4_t const genre_HEAVY_METAL[] =
- { 'H', 'e', 'a', 'v', 'y', ' ', 'M', 'e', 't', 'a', 'l', 0 };
-static id3_ucs4_t const genre_BLACK_METAL[] =
- { 'B', 'l', 'a', 'c', 'k', ' ', 'M', 'e', 't', 'a', 'l', 0 };
-static id3_ucs4_t const genre_CROSSOVER[] =
- { 'C', 'r', 'o', 's', 's', 'o', 'v', 'e', 'r', 0 };
-static id3_ucs4_t const genre_CONTEMPORARY_CHRISTIAN[] =
- { 'C', 'o', 'n', 't', 'e', 'm', 'p', 'o', 'r', 'a', 'r', 'y', ' ', 'C', 'h', 'r', 'i', 's', 't', 'i', 'a', 'n', 0 };
-static id3_ucs4_t const genre_CHRISTIAN_ROCK[] =
- { 'C', 'h', 'r', 'i', 's', 't', 'i', 'a', 'n', ' ', 'R', 'o', 'c', 'k', 0 };
-static id3_ucs4_t const genre_MERENGUE[] =
- { 'M', 'e', 'r', 'e', 'n', 'g', 'u', 'e', 0 };
-static id3_ucs4_t const genre_SALSA[] =
- { 'S', 'a', 'l', 's', 'a', 0 };
-static id3_ucs4_t const genre_THRASH_METAL[] =
- { 'T', 'h', 'r', 'a', 's', 'h', ' ', 'M', 'e', 't', 'a', 'l', 0 };
-static id3_ucs4_t const genre_ANIME[] =
- { 'A', 'n', 'i', 'm', 'e', 0 };
-static id3_ucs4_t const genre_JPOP[] =
- { 'J', 'P', 'o', 'p', 0 };
-static id3_ucs4_t const genre_SYNTHPOP[] =
- { 'S', 'y', 'n', 't', 'h', 'p', 'o', 'p', 0 };
-
-static id3_ucs4_t const *const genre_table[] = {
- genre_BLUES,
- genre_CLASSIC_ROCK,
- genre_COUNTRY,
- genre_DANCE,
- genre_DISCO,
- genre_FUNK,
- genre_GRUNGE,
- genre_HIP_HOP,
- genre_JAZZ,
- genre_METAL,
- genre_NEW_AGE,
- genre_OLDIES,
- genre_OTHER,
- genre_POP,
- genre_R_B,
- genre_RAP,
- genre_REGGAE,
- genre_ROCK,
- genre_TECHNO,
- genre_INDUSTRIAL,
- genre_ALTERNATIVE,
- genre_SKA,
- genre_DEATH_METAL,
- genre_PRANKS,
- genre_SOUNDTRACK,
- genre_EURO_TECHNO,
- genre_AMBIENT,
- genre_TRIP_HOP,
- genre_VOCAL,
- genre_JAZZ_FUNK,
- genre_FUSION,
- genre_TRANCE,
- genre_CLASSICAL,
- genre_INSTRUMENTAL,
- genre_ACID,
- genre_HOUSE,
- genre_GAME,
- genre_SOUND_CLIP,
- genre_GOSPEL,
- genre_NOISE,
- genre_ALTERNROCK,
- genre_BASS,
- genre_SOUL,
- genre_PUNK,
- genre_SPACE,
- genre_MEDITATIVE,
- genre_INSTRUMENTAL_POP,
- genre_INSTRUMENTAL_ROCK,
- genre_ETHNIC,
- genre_GOTHIC,
- genre_DARKWAVE,
- genre_TECHNO_INDUSTRIAL,
- genre_ELECTRONIC,
- genre_POP_FOLK,
- genre_EURODANCE,
- genre_DREAM,
- genre_SOUTHERN_ROCK,
- genre_COMEDY,
- genre_CULT,
- genre_GANGSTA,
- genre_TOP_40,
- genre_CHRISTIAN_RAP,
- genre_POP_FUNK,
- genre_JUNGLE,
- genre_NATIVE_AMERICAN,
- genre_CABARET,
- genre_NEW_WAVE,
- genre_PSYCHEDELIC,
- genre_RAVE,
- genre_SHOWTUNES,
- genre_TRAILER,
- genre_LO_FI,
- genre_TRIBAL,
- genre_ACID_PUNK,
- genre_ACID_JAZZ,
- genre_POLKA,
- genre_RETRO,
- genre_MUSICAL,
- genre_ROCK___ROLL,
- genre_HARD_ROCK,
- genre_FOLK,
- genre_FOLK_ROCK,
- genre_NATIONAL_FOLK,
- genre_SWING,
- genre_FAST_FUSION,
- genre_BEBOB,
- genre_LATIN,
- genre_REVIVAL,
- genre_CELTIC,
- genre_BLUEGRASS,
- genre_AVANTGARDE,
- genre_GOTHIC_ROCK,
- genre_PROGRESSIVE_ROCK,
- genre_PSYCHEDELIC_ROCK,
- genre_SYMPHONIC_ROCK,
- genre_SLOW_ROCK,
- genre_BIG_BAND,
- genre_CHORUS,
- genre_EASY_LISTENING,
- genre_ACOUSTIC,
- genre_HUMOUR,
- genre_SPEECH,
- genre_CHANSON,
- genre_OPERA,
- genre_CHAMBER_MUSIC,
- genre_SONATA,
- genre_SYMPHONY,
- genre_BOOTY_BASS,
- genre_PRIMUS,
- genre_PORN_GROOVE,
- genre_SATIRE,
- genre_SLOW_JAM,
- genre_CLUB,
- genre_TANGO,
- genre_SAMBA,
- genre_FOLKLORE,
- genre_BALLAD,
- genre_POWER_BALLAD,
- genre_RHYTHMIC_SOUL,
- genre_FREESTYLE,
- genre_DUET,
- genre_PUNK_ROCK,
- genre_DRUM_SOLO,
- genre_A_CAPPELLA,
- genre_EURO_HOUSE,
- genre_DANCE_HALL,
- genre_GOA,
- genre_DRUM___BASS,
- genre_CLUB_HOUSE,
- genre_HARDCORE,
- genre_TERROR,
- genre_INDIE,
- genre_BRITPOP,
- genre_NEGERPUNK,
- genre_POLSK_PUNK,
- genre_BEAT,
- genre_CHRISTIAN_GANGSTA_RAP,
- genre_HEAVY_METAL,
- genre_BLACK_METAL,
- genre_CROSSOVER,
- genre_CONTEMPORARY_CHRISTIAN,
- genre_CHRISTIAN_ROCK,
- genre_MERENGUE,
- genre_SALSA,
- genre_THRASH_METAL,
- genre_ANIME,
- genre_JPOP,
- genre_SYNTHPOP
-};
diff --git a/src/libid3tag/genre.dat.in b/src/libid3tag/genre.dat.in
deleted file mode 100644
index 872de40..0000000
--- a/src/libid3tag/genre.dat.in
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: genre.dat.in,v 1.7 2004/01/23 09:41:32 rob Exp $
- */
-
-/*
- * These are the ID3 genre names, taken as a combination of names from ID3v1
- * (listed in Appendix A of the ID3 tag version 2.4.0 informal standard) and
- * the extensions made by Winamp as of version 2.80.
- */
-
-/* ID3v1 names (0-79) */
-
-Blues
-Classic Rock
-Country
-Dance
-Disco
-Funk
-Grunge
-Hip-Hop
-Jazz
-Metal
-New Age
-Oldies
-Other
-Pop
-R&B
-Rap
-Reggae
-Rock
-Techno
-Industrial
-Alternative
-Ska
-Death Metal
-Pranks
-Soundtrack
-Euro-Techno
-Ambient
-Trip-Hop
-Vocal
-Jazz+Funk
-Fusion
-Trance
-Classical
-Instrumental
-Acid
-House
-Game
-Sound Clip
-Gospel
-Noise
-AlternRock
-Bass
-Soul
-Punk
-Space
-Meditative
-Instrumental Pop
-Instrumental Rock
-Ethnic
-Gothic
-Darkwave
-Techno-Industrial
-Electronic
-Pop-Folk
-Eurodance
-Dream
-Southern Rock
-Comedy
-Cult
-Gangsta
-Top 40
-Christian Rap
-Pop/Funk
-Jungle
-Native American
-Cabaret
-New Wave
-Psychedelic
-Rave
-Showtunes
-Trailer
-Lo-Fi
-Tribal
-Acid Punk
-Acid Jazz
-Polka
-Retro
-Musical
-Rock & Roll
-Hard Rock
-
-/* Winamp extensions (80-147) */
-
-Folk
-Folk/Rock
-National Folk
-Swing
-Fast-Fusion
-Bebob
-Latin
-Revival
-Celtic
-Bluegrass
-Avantgarde
-Gothic Rock
-Progressive Rock
-Psychedelic Rock
-Symphonic Rock
-Slow Rock
-Big Band
-Chorus
-Easy Listening
-Acoustic
-Humour
-Speech
-Chanson
-Opera
-Chamber Music
-Sonata
-Symphony
-Booty Bass
-Primus
-Porn Groove
-Satire
-Slow Jam
-Club
-Tango
-Samba
-Folklore
-Ballad
-Power Ballad
-Rhythmic Soul
-Freestyle
-Duet
-Punk Rock
-Drum Solo
-A Cappella
-Euro-House
-Dance Hall
-Goa
-Drum & Bass
-Club-House
-Hardcore
-Terror
-Indie
-BritPop
-Negerpunk
-Polsk Punk
-Beat
-Christian Gangsta Rap
-Heavy Metal
-Black Metal
-Crossover
-Contemporary Christian
-Christian Rock
-Merengue
-Salsa
-Thrash Metal
-Anime
-JPop
-Synthpop
diff --git a/src/libid3tag/genre.dat.sed b/src/libid3tag/genre.dat.sed
deleted file mode 100644
index b8be6c5..0000000
--- a/src/libid3tag/genre.dat.sed
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# libid3tag - ID3 tag manipulation library
-# Copyright (C) 2000-2004 Underbit Technologies, Inc.
-#
-# 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 program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
-# $Id: genre.dat.sed,v 1.10 2004/01/23 09:41:32 rob Exp $
-#
-
-1i\
-/* Automatically generated from genre.dat.in */
-
-# generate an array from a string
-/^[A-Za-z]/{
-H
-y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
-s/[^A-Z0-9]/_/g
-s/.*/static id3_ucs4_t const genre_&[] =/p
-g
-s/.*\n//
-s/./'&', /g
-s/.*/ { &0 };/
-}
-
-# write the final table of arrays
-${
-p
-i\
-\
-static id3_ucs4_t const *const genre_table[] = {
-g
-s/^\(\n\)\(.*\)$/\2\1/
-y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
-s/[^A-Z0-9\n]/_/g
-s/\([^\n]*\)\(\n\)/ genre_\1,\2/g
-s/,\n$//
-a\
-};
-}
-
-# print the pattern space (assumes -n)
-p
diff --git a/src/libid3tag/genre.h b/src/libid3tag/genre.h
deleted file mode 100644
index 56d538a..0000000
--- a/src/libid3tag/genre.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: genre.h,v 1.6 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_GENRE_H
-# define LIBID3TAG_GENRE_H
-
-# define ID3_GENRE_OTHER 12
-
-# endif
diff --git a/src/libid3tag/global.h b/src/libid3tag/global.h
deleted file mode 100644
index 377a5e6..0000000
--- a/src/libid3tag/global.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: global.h,v 1.9 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_GLOBAL_H
-# define LIBID3TAG_GLOBAL_H
-
-/* conditional debugging */
-
-# if defined(DEBUG) && defined(NDEBUG)
-# error "cannot define both DEBUG and NDEBUG"
-# endif
-
-# if defined(DEBUG)
-# include <stdio.h>
-# include "debug.h"
-# define malloc(sz) id3_debug_malloc(sz, __FILE__, __LINE__)
-# define calloc(n, sz) id3_debug_calloc(n, sz, __FILE__, __LINE__)
-# define realloc(ptr, sz) id3_debug_realloc(ptr, sz, __FILE__, __LINE__)
-# define free(ptr) id3_debug_free(ptr, __FILE__, __LINE__)
-# define release(ptr) id3_debug_release(ptr, __FILE__, __LINE__)
-# else
-# define release(ptr) (ptr)
-# endif
-
-/* conditional features */
-
-# if !defined(HAVE_ASSERT_H)
-# if defined(NDEBUG)
-# define assert(x) /* nothing */
-# else
-# define assert(x) do { if (!(x)) abort(); } while (0)
-# endif
-# endif
-
-# endif
diff --git a/src/libid3tag/id3tag.h b/src/libid3tag/id3tag.h
deleted file mode 100644
index fc9bbfd..0000000
--- a/src/libid3tag/id3tag.h
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * If you would like to negotiate alternate licensing terms, you may do
- * so by contacting: Underbit Technologies, Inc. <info@underbit.com>
- *
- * $Id: id3tag.h,v 1.17 2004/01/23 23:22:46 rob Exp $
- */
-
-# ifndef LIBID3TAG_ID3TAG_H
-# define LIBID3TAG_ID3TAG_H
-
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-#include "libaudcore/vfs.h"
-
-# define ID3_TAG_VERSION 0x0400
-# define ID3_TAG_VERSION_MAJOR(x) (((x) >> 8) & 0xff)
-# define ID3_TAG_VERSION_MINOR(x) (((x) >> 0) & 0xff)
-
-typedef unsigned char id3_byte_t;
-typedef unsigned long id3_length_t;
-
-typedef unsigned long id3_ucs4_t;
-
-typedef unsigned char id3_latin1_t;
-typedef unsigned short id3_utf16_t;
-typedef signed char id3_utf8_t;
-
-struct id3_tag {
- unsigned int refcount;
- unsigned int version;
- int flags;
- int extendedflags;
- int restrictions;
- int options;
- unsigned int nframes;
- struct id3_frame **frames;
- id3_length_t paddedsize;
-};
-
-# define ID3_TAG_QUERYSIZE 10
-
-/* ID3v1 field frames */
-
-# define ID3_FRAME_TITLE "TIT2"
-# define ID3_FRAME_ARTIST "TPE1"
-# define ID3_FRAME_ALBUM "TALB"
-# define ID3_FRAME_TRACK "TRCK"
-# define ID3_FRAME_YEAR "TDRC"
-# define ID3_FRAME_GENRE "TCON"
-# define ID3_FRAME_COMMENT "COMM"
-
-/* special frames */
-
-# define ID3_FRAME_OBSOLETE "ZOBS" /* with apologies to the French */
-
-/* tag flags */
-
-enum {
- ID3_TAG_FLAG_UNSYNCHRONISATION = 0x80,
- ID3_TAG_FLAG_EXTENDEDHEADER = 0x40,
- ID3_TAG_FLAG_EXPERIMENTALINDICATOR = 0x20,
- ID3_TAG_FLAG_FOOTERPRESENT = 0x10,
-
- ID3_TAG_FLAG_KNOWNFLAGS = 0xf0
-};
-
-/* tag extended flags */
-
-enum {
- ID3_TAG_EXTENDEDFLAG_TAGISANUPDATE = 0x40,
- ID3_TAG_EXTENDEDFLAG_CRCDATAPRESENT = 0x20,
- ID3_TAG_EXTENDEDFLAG_TAGRESTRICTIONS = 0x10,
-
- ID3_TAG_EXTENDEDFLAG_KNOWNFLAGS = 0x70
-};
-
-/* tag restrictions */
-
-enum {
- ID3_TAG_RESTRICTION_TAGSIZE_MASK = 0xc0,
- ID3_TAG_RESTRICTION_TAGSIZE_128_FRAMES_1_MB = 0x00,
- ID3_TAG_RESTRICTION_TAGSIZE_64_FRAMES_128_KB = 0x40,
- ID3_TAG_RESTRICTION_TAGSIZE_32_FRAMES_40_KB = 0x80,
- ID3_TAG_RESTRICTION_TAGSIZE_32_FRAMES_4_KB = 0xc0
-};
-
-enum {
- ID3_TAG_RESTRICTION_TEXTENCODING_MASK = 0x20,
- ID3_TAG_RESTRICTION_TEXTENCODING_NONE = 0x00,
- ID3_TAG_RESTRICTION_TEXTENCODING_LATIN1_UTF8 = 0x20
-};
-
-enum {
- ID3_TAG_RESTRICTION_TEXTSIZE_MASK = 0x18,
- ID3_TAG_RESTRICTION_TEXTSIZE_NONE = 0x00,
- ID3_TAG_RESTRICTION_TEXTSIZE_1024_CHARS = 0x08,
- ID3_TAG_RESTRICTION_TEXTSIZE_128_CHARS = 0x10,
- ID3_TAG_RESTRICTION_TEXTSIZE_30_CHARS = 0x18
-};
-
-enum {
- ID3_TAG_RESTRICTION_IMAGEENCODING_MASK = 0x04,
- ID3_TAG_RESTRICTION_IMAGEENCODING_NONE = 0x00,
- ID3_TAG_RESTRICTION_IMAGEENCODING_PNG_JPEG = 0x04
-};
-
-enum {
- ID3_TAG_RESTRICTION_IMAGESIZE_MASK = 0x03,
- ID3_TAG_RESTRICTION_IMAGESIZE_NONE = 0x00,
- ID3_TAG_RESTRICTION_IMAGESIZE_256_256 = 0x01,
- ID3_TAG_RESTRICTION_IMAGESIZE_64_64 = 0x02,
- ID3_TAG_RESTRICTION_IMAGESIZE_64_64_EXACT = 0x03
-};
-
-/* library options */
-
-enum {
- ID3_TAG_OPTION_UNSYNCHRONISATION = 0x0001, /* use unsynchronisation */
- ID3_TAG_OPTION_COMPRESSION = 0x0002, /* use compression */
- ID3_TAG_OPTION_CRC = 0x0004, /* use CRC */
-
- ID3_TAG_OPTION_APPENDEDTAG = 0x0010, /* tag will be appended */
- ID3_TAG_OPTION_FILEALTERED = 0x0020, /* audio data was altered */
-
- ID3_TAG_OPTION_ID3V1 = 0x0100 /* render ID3v1/ID3v1.1 tag */
-};
-
-struct id3_frame {
- char id[5];
- char const *description;
- unsigned int refcount;
- int flags;
- int group_id;
- int encryption_method;
- id3_byte_t *encoded;
- id3_length_t encoded_length;
- id3_length_t decoded_length;
- unsigned int nfields;
- union id3_field *fields;
-};
-
-enum {
- /* frame status flags */
- ID3_FRAME_FLAG_TAGALTERPRESERVATION = 0x4000,
- ID3_FRAME_FLAG_FILEALTERPRESERVATION = 0x2000,
- ID3_FRAME_FLAG_READONLY = 0x1000,
-
- ID3_FRAME_FLAG_STATUSFLAGS = 0xff00,
-
- /* frame format flags */
- ID3_FRAME_FLAG_GROUPINGIDENTITY = 0x0040,
- ID3_FRAME_FLAG_COMPRESSION = 0x0008,
- ID3_FRAME_FLAG_ENCRYPTION = 0x0004,
- ID3_FRAME_FLAG_UNSYNCHRONISATION = 0x0002,
- ID3_FRAME_FLAG_DATALENGTHINDICATOR = 0x0001,
-
- ID3_FRAME_FLAG_FORMATFLAGS = 0x00ff,
-
- ID3_FRAME_FLAG_KNOWNFLAGS = 0x704f
-};
-
-enum id3_field_type {
- ID3_FIELD_TYPE_TEXTENCODING,
- ID3_FIELD_TYPE_LATIN1,
- ID3_FIELD_TYPE_LATIN1FULL,
- ID3_FIELD_TYPE_LATIN1LIST,
- ID3_FIELD_TYPE_STRING,
- ID3_FIELD_TYPE_STRINGFULL,
- ID3_FIELD_TYPE_STRINGLIST,
- ID3_FIELD_TYPE_LANGUAGE,
- ID3_FIELD_TYPE_FRAMEID,
- ID3_FIELD_TYPE_DATE,
- ID3_FIELD_TYPE_INT8,
- ID3_FIELD_TYPE_INT16,
- ID3_FIELD_TYPE_INT24,
- ID3_FIELD_TYPE_INT32,
- ID3_FIELD_TYPE_INT32PLUS,
- ID3_FIELD_TYPE_BINARYDATA
-};
-
-enum id3_field_textencoding {
- ID3_FIELD_TEXTENCODING_ISO_8859_1 = 0x00,
- ID3_FIELD_TEXTENCODING_UTF_16 = 0x01,
- ID3_FIELD_TEXTENCODING_UTF_16BE = 0x02,
- ID3_FIELD_TEXTENCODING_UTF_8 = 0x03
-};
-
-union id3_field {
- enum id3_field_type type;
- struct {
- enum id3_field_type type;
- signed long value;
- } number;
- struct {
- enum id3_field_type type;
- id3_latin1_t *ptr;
- } latin1;
- struct {
- enum id3_field_type type;
- unsigned int nstrings;
- id3_latin1_t **strings;
- } latin1list;
- struct {
- enum id3_field_type type;
- id3_ucs4_t *ptr;
- } string;
- struct {
- enum id3_field_type type;
- unsigned int nstrings;
- id3_ucs4_t **strings;
- } stringlist;
- struct {
- enum id3_field_type type;
- char value[9];
- } immediate;
- struct {
- enum id3_field_type type;
- id3_byte_t *data;
- id3_length_t length;
- } binary;
-};
-
-/* file interface */
-
-enum id3_file_mode {
- ID3_FILE_MODE_READONLY = 0,
- ID3_FILE_MODE_READWRITE
-};
-
-struct id3_file *id3_file_open(char const *, enum id3_file_mode);
-struct id3_file *id3_file_vfsopen(VFSFile *, enum id3_file_mode);
-struct id3_file *id3_file_fdopen(int, enum id3_file_mode);
-int id3_file_close(struct id3_file *);
-
-struct id3_tag *id3_file_tag(struct id3_file const *);
-
-int id3_file_update(struct id3_file *);
-
-/* tag interface */
-
-struct id3_tag *id3_tag_new(void);
-void id3_tag_delete(struct id3_tag *);
-
-unsigned int id3_tag_version(struct id3_tag const *);
-
-int id3_tag_options(struct id3_tag *, int, int);
-void id3_tag_setlength(struct id3_tag *, id3_length_t);
-
-void id3_tag_clearframes(struct id3_tag *);
-
-int id3_tag_attachframe(struct id3_tag *, struct id3_frame *);
-int id3_tag_detachframe(struct id3_tag *, struct id3_frame *);
-
-struct id3_frame *id3_tag_findframe(struct id3_tag const *,
- char const *, unsigned int);
-
-signed long id3_tag_query(id3_byte_t const *, id3_length_t);
-
-struct id3_tag *id3_tag_parse(id3_byte_t const *, id3_length_t);
-id3_length_t id3_tag_render(struct id3_tag const *, id3_byte_t *);
-
-/* frame interface */
-
-struct id3_frame *id3_frame_new(char const *);
-void id3_frame_delete(struct id3_frame *);
-
-union id3_field *id3_frame_field(struct id3_frame const *, unsigned int);
-
-/* field interface */
-
-enum id3_field_type id3_field_type(union id3_field const *);
-
-int id3_field_setint(union id3_field *, signed long);
-int id3_field_settextencoding(union id3_field *, enum id3_field_textencoding);
-int id3_field_setstrings(union id3_field *, unsigned int, id3_ucs4_t **);
-int id3_field_addstring(union id3_field *, id3_ucs4_t const *);
-int id3_field_setlanguage(union id3_field *, char const *);
-int id3_field_setlatin1(union id3_field *, id3_latin1_t const *);
-int id3_field_setfulllatin1(union id3_field *, id3_latin1_t const *);
-int id3_field_setstring(union id3_field *, id3_ucs4_t const *);
-int id3_field_setfullstring(union id3_field *, id3_ucs4_t const *);
-int id3_field_setframeid(union id3_field *, char const *);
-int id3_field_setbinarydata(union id3_field *,
- id3_byte_t const *, id3_length_t);
-
-signed long id3_field_getint(union id3_field const *);
-enum id3_field_textencoding id3_field_gettextencoding(union id3_field const *);
-id3_latin1_t const *id3_field_getlatin1(union id3_field const *);
-id3_latin1_t const *id3_field_getfulllatin1(union id3_field const *);
-id3_ucs4_t const *id3_field_getstring(union id3_field const *);
-id3_ucs4_t const *id3_field_getfullstring(union id3_field const *);
-unsigned int id3_field_getnstrings(union id3_field const *);
-id3_ucs4_t const *id3_field_getstrings(union id3_field const *,
- unsigned int);
-char const *id3_field_getframeid(union id3_field const *);
-id3_byte_t const *id3_field_getbinarydata(union id3_field const *,
- id3_length_t *);
-
-/* genre interface */
-
-id3_ucs4_t const *id3_genre_index(unsigned int);
-id3_ucs4_t const *id3_genre_name(id3_ucs4_t const *);
-int id3_genre_number(id3_ucs4_t const *);
-
-/* ucs4 interface */
-
-id3_latin1_t *id3_ucs4_latin1duplicate(id3_ucs4_t const *);
-id3_utf16_t *id3_ucs4_utf16duplicate(id3_ucs4_t const *);
-id3_utf8_t *id3_ucs4_utf8duplicate(id3_ucs4_t const *);
-
-void id3_ucs4_putnumber(id3_ucs4_t *, unsigned long);
-unsigned long id3_ucs4_getnumber(id3_ucs4_t const *);
-
-/* latin1/utf16/utf8 interfaces */
-
-id3_ucs4_t *id3_latin1_ucs4duplicate(id3_latin1_t const *);
-id3_ucs4_t *id3_utf16_ucs4duplicate(id3_utf16_t const *);
-id3_ucs4_t *id3_utf8_ucs4duplicate(id3_utf8_t const *);
-
-/* version interface */
-
-# define ID3_VERSION_MAJOR 0
-# define ID3_VERSION_MINOR 15
-# define ID3_VERSION_PATCH 1
-# define ID3_VERSION_EXTRA " (beta)"
-
-# define ID3_VERSION_STRINGIZE(str) #str
-# define ID3_VERSION_STRING(num) ID3_VERSION_STRINGIZE(num)
-
-# define ID3_VERSION ID3_VERSION_STRING(ID3_VERSION_MAJOR) "." \
- ID3_VERSION_STRING(ID3_VERSION_MINOR) "." \
- ID3_VERSION_STRING(ID3_VERSION_PATCH) \
- ID3_VERSION_EXTRA
-
-# define ID3_PUBLISHYEAR "2000-2004"
-# define ID3_AUTHOR "Underbit Technologies, Inc."
-# define ID3_EMAIL "info@underbit.com"
-
-extern char const id3_version[];
-extern char const id3_copyright[];
-extern char const id3_author[];
-extern char const id3_build[];
-
-# ifdef __cplusplus
-}
-# endif
-
-# endif
diff --git a/src/libid3tag/latin1.c b/src/libid3tag/latin1.c
deleted file mode 100644
index 67b8199..0000000
--- a/src/libid3tag/latin1.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: latin1.c,v 1.10 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <stdlib.h>
-
-# include "id3tag.h"
-# include "latin1.h"
-# include "ucs4.h"
-
-/*
- * NAME: latin1->length()
- * DESCRIPTION: return the number of ucs4 chars represented by a latin1 string
- */
-id3_length_t id3_latin1_length(id3_latin1_t const *latin1)
-{
- id3_latin1_t const *ptr = latin1;
-
- while (*ptr)
- ++ptr;
-
- return ptr - latin1;
-}
-
-/*
- * NAME: latin1->size()
- * DESCRIPTION: return the encoding size of a latin1 string
- */
-id3_length_t id3_latin1_size(id3_latin1_t const *latin1)
-{
- return id3_latin1_length(latin1) + 1;
-}
-
-/*
- * NAME: latin1->copy()
- * DESCRIPTION: copy a latin1 string
- */
-void id3_latin1_copy(id3_latin1_t *dest, id3_latin1_t const *src)
-{
- while ((*dest++ = *src++))
- ;
-}
-
-/*
- * NAME: latin1->duplicate()
- * DESCRIPTION: duplicate a latin1 string
- */
-id3_latin1_t *id3_latin1_duplicate(id3_latin1_t const *src)
-{
- id3_latin1_t *latin1;
-
- latin1 = malloc(id3_latin1_size(src) * sizeof(*latin1));
- if (latin1)
- id3_latin1_copy(latin1, src);
-
- return latin1;
-}
-
-/*
- * NAME: latin1->ucs4duplicate()
- * DESCRIPTION: duplicate and decode a latin1 string into ucs4
- */
-id3_ucs4_t *id3_latin1_ucs4duplicate(id3_latin1_t const *latin1)
-{
- id3_ucs4_t *ucs4;
-
- ucs4 = malloc((id3_latin1_length(latin1) + 1) * sizeof(*ucs4));
- if (ucs4)
- id3_latin1_decode(latin1, ucs4);
-
- return release(ucs4);
-}
-
-/*
- * NAME: latin1->decodechar()
- * DESCRIPTION: decode a (single) latin1 char into a single ucs4 char
- */
-id3_length_t id3_latin1_decodechar(id3_latin1_t const *latin1,
- id3_ucs4_t *ucs4)
-{
- *ucs4 = *latin1;
-
- return 1;
-}
-
-/*
- * NAME: latin1->encodechar()
- * DESCRIPTION: encode a single ucs4 char into a (single) latin1 char
- */
-id3_length_t id3_latin1_encodechar(id3_latin1_t *latin1, id3_ucs4_t ucs4)
-{
- *latin1 = ucs4;
- if (ucs4 > 0x000000ffL)
- *latin1 = ID3_UCS4_REPLACEMENTCHAR;
-
- return 1;
-}
-
-/*
- * NAME: latin1->decode()
- * DESCRIPTION: decode a complete latin1 string into a ucs4 string
- */
-void id3_latin1_decode(id3_latin1_t const *latin1, id3_ucs4_t *ucs4)
-{
- do
- latin1 += id3_latin1_decodechar(latin1, ucs4);
- while (*ucs4++);
-}
-
-/*
- * NAME: latin1->encode()
- * DESCRIPTION: encode a complete ucs4 string into a latin1 string
- */
-void id3_latin1_encode(id3_latin1_t *latin1, id3_ucs4_t const *ucs4)
-{
- do
- latin1 += id3_latin1_encodechar(latin1, *ucs4);
- while (*ucs4++);
-}
-
-/*
- * NAME: latin1->put()
- * DESCRIPTION: serialize a single latin1 character
- */
-id3_length_t id3_latin1_put(id3_byte_t **ptr, id3_latin1_t latin1)
-{
- if (ptr)
- *(*ptr)++ = latin1;
-
- return 1;
-}
-
-/*
- * NAME: latin1->get()
- * DESCRIPTION: deserialize a single latin1 character
- */
-id3_latin1_t id3_latin1_get(id3_byte_t const **ptr)
-{
- return *(*ptr)++;
-}
-
-/*
- * NAME: latin1->serialize()
- * DESCRIPTION: serialize a ucs4 string using latin1 encoding
- */
-id3_length_t id3_latin1_serialize(id3_byte_t **ptr, id3_ucs4_t const *ucs4,
- int terminate)
-{
- id3_length_t size = 0;
- id3_latin1_t latin1[1], *out;
-
- while (*ucs4) {
- switch (id3_latin1_encodechar(out = latin1, *ucs4++)) {
- case 1: size += id3_latin1_put(ptr, *out++);
- case 0: break;
- }
- }
-
- if (terminate)
- size += id3_latin1_put(ptr, 0);
-
- return size;
-}
-
-/*
- * NAME: latin1->deserialize()
- * DESCRIPTION: deserialize a ucs4 string using latin1 encoding
- */
-id3_ucs4_t *id3_latin1_deserialize(id3_byte_t const **ptr, id3_length_t length)
-{
- id3_byte_t const *end;
- id3_latin1_t *latin1ptr, *latin1;
- id3_ucs4_t *ucs4;
-
- end = *ptr + length;
-
- latin1 = malloc((length + 1) * sizeof(*latin1));
- if (latin1 == 0)
- return 0;
-
- latin1ptr = latin1;
- while (end - *ptr > 0 && (*latin1ptr = id3_latin1_get(ptr)))
- ++latin1ptr;
-
- *latin1ptr = 0;
-
- ucs4 = malloc((id3_latin1_length(latin1) + 1) * sizeof(*ucs4));
- if (ucs4)
- id3_latin1_decode(latin1, ucs4);
-
- free(latin1);
-
- return ucs4;
-}
diff --git a/src/libid3tag/latin1.h b/src/libid3tag/latin1.h
deleted file mode 100644
index 3604bbf..0000000
--- a/src/libid3tag/latin1.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: latin1.h,v 1.8 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_LATIN1_H
-# define LIBID3TAG_LATIN1_H
-
-# include "id3tag.h"
-
-id3_length_t id3_latin1_length(id3_latin1_t const *);
-id3_length_t id3_latin1_size(id3_latin1_t const *);
-
-void id3_latin1_copy(id3_latin1_t *, id3_latin1_t const *);
-id3_latin1_t *id3_latin1_duplicate(id3_latin1_t const *);
-
-id3_length_t id3_latin1_decodechar(id3_latin1_t const *, id3_ucs4_t *);
-id3_length_t id3_latin1_encodechar(id3_latin1_t *, id3_ucs4_t);
-
-void id3_latin1_decode(id3_latin1_t const *, id3_ucs4_t *);
-void id3_latin1_encode(id3_latin1_t *, id3_ucs4_t const *);
-
-id3_length_t id3_latin1_put(id3_byte_t **, id3_latin1_t);
-id3_latin1_t id3_latin1_get(id3_byte_t const **);
-
-id3_length_t id3_latin1_serialize(id3_byte_t **, id3_ucs4_t const *, int);
-id3_ucs4_t *id3_latin1_deserialize(id3_byte_t const **, id3_length_t);
-
-# endif
diff --git a/src/libid3tag/parse.c b/src/libid3tag/parse.c
deleted file mode 100644
index 86a3f21..0000000
--- a/src/libid3tag/parse.c
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: parse.c,v 1.9 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# ifdef HAVE_ASSERT_H
-# include <assert.h>
-# endif
-
-# include <stdlib.h>
-# include <string.h>
-
-# include "id3tag.h"
-# include "parse.h"
-# include "latin1.h"
-# include "utf16.h"
-# include "utf8.h"
-
-signed long id3_parse_int(id3_byte_t const **ptr, unsigned int bytes)
-{
- signed long value = 0;
-
- assert(bytes >= 1 && bytes <= 4);
-
- if (**ptr & 0x80)
- value = ~0;
-
- switch (bytes) {
- case 4: value = (value << 8) | *(*ptr)++;
- case 3: value = (value << 8) | *(*ptr)++;
- case 2: value = (value << 8) | *(*ptr)++;
- case 1: value = (value << 8) | *(*ptr)++;
- }
-
- return value;
-}
-
-unsigned long id3_parse_uint(id3_byte_t const **ptr, unsigned int bytes)
-{
- unsigned long value = 0;
-
- assert(bytes >= 1 && bytes <= 4);
-
- switch (bytes) {
- case 4: value = (value << 8) | *(*ptr)++;
- case 3: value = (value << 8) | *(*ptr)++;
- case 2: value = (value << 8) | *(*ptr)++;
- case 1: value = (value << 8) | *(*ptr)++;
- }
-
- return value;
-}
-
-unsigned long id3_parse_syncsafe(id3_byte_t const **ptr, unsigned int bytes)
-{
- unsigned long value = 0;
-
- assert(bytes == 4 || bytes == 5);
-
- switch (bytes) {
- case 5: value = (value << 4) | (*(*ptr)++ & 0x0f);
- case 4: value = (value << 7) | (*(*ptr)++ & 0x7f);
- value = (value << 7) | (*(*ptr)++ & 0x7f);
- value = (value << 7) | (*(*ptr)++ & 0x7f);
- value = (value << 7) | (*(*ptr)++ & 0x7f);
- }
-
- return value;
-}
-
-void id3_parse_immediate(id3_byte_t const **ptr, unsigned int bytes,
- char *value)
-{
- assert(value);
- assert(bytes == 8 || bytes == 4 || bytes == 3);
-
- switch (bytes) {
- case 8: *value++ = *(*ptr)++;
- *value++ = *(*ptr)++;
- *value++ = *(*ptr)++;
- *value++ = *(*ptr)++;
- case 4: *value++ = *(*ptr)++;
- case 3: *value++ = *(*ptr)++;
- *value++ = *(*ptr)++;
- *value++ = *(*ptr)++;
- }
-
- *value = 0;
-}
-
-id3_latin1_t *id3_parse_latin1(id3_byte_t const **ptr, id3_length_t length,
- int full)
-{
- id3_byte_t const *end;
- int terminated = 0;
- id3_latin1_t *latin1;
-
- end = memchr(*ptr, 0, length);
- if (end == 0)
- end = *ptr + length;
- else {
- length = end - *ptr;
- terminated = 1;
- }
-
- latin1 = malloc(length + 1);
- if (latin1) {
- memcpy(latin1, *ptr, length);
- latin1[length] = 0;
-
- if (!full) {
- id3_latin1_t *check;
-
- for (check = latin1; *check; ++check) {
- if (*check == '\n')
- *check = ' ';
- }
- }
- }
-
- *ptr += length + terminated;
-
- return latin1;
-}
-
-id3_ucs4_t *id3_parse_string(id3_byte_t const **ptr, id3_length_t length,
- enum id3_field_textencoding encoding, int full)
-{
- id3_ucs4_t *ucs4 = 0;
- enum id3_utf16_byteorder byteorder = ID3_UTF16_BYTEORDER_ANY;
-
- switch (encoding) {
- case ID3_FIELD_TEXTENCODING_ISO_8859_1:
- ucs4 = id3_latin1_deserialize(ptr, length);
- break;
-
- case ID3_FIELD_TEXTENCODING_UTF_16BE:
- byteorder = ID3_UTF16_BYTEORDER_BE;
- case ID3_FIELD_TEXTENCODING_UTF_16:
- ucs4 = id3_utf16_deserialize(ptr, length, byteorder);
- break;
-
- case ID3_FIELD_TEXTENCODING_UTF_8:
- ucs4 = id3_utf8_deserialize(ptr, length);
- break;
- }
-
- if (ucs4 && !full) {
- id3_ucs4_t *check;
-
- for (check = ucs4; *check; ++check) {
- if (*check == '\n')
- *check = ' ';
- }
- }
-
- return ucs4;
-}
-
-id3_byte_t *id3_parse_binary(id3_byte_t const **ptr, id3_length_t length)
-{
- id3_byte_t *data;
-
- if (length == 0)
- return malloc(1);
-
- data = malloc(length);
- if (data)
- memcpy(data, *ptr, length);
-
- *ptr += length;
-
- return data;
-}
diff --git a/src/libid3tag/parse.h b/src/libid3tag/parse.h
deleted file mode 100644
index 5dfa23f..0000000
--- a/src/libid3tag/parse.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: parse.h,v 1.6 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_PARSE_H
-# define LIBID3TAG_PARSE_H
-
-signed long id3_parse_int(id3_byte_t const **, unsigned int);
-unsigned long id3_parse_uint(id3_byte_t const **, unsigned int);
-unsigned long id3_parse_syncsafe(id3_byte_t const **, unsigned int);
-void id3_parse_immediate(id3_byte_t const **, unsigned int, char *);
-id3_latin1_t *id3_parse_latin1(id3_byte_t const **, id3_length_t, int);
-id3_ucs4_t *id3_parse_string(id3_byte_t const **, id3_length_t,
- enum id3_field_textencoding, int);
-id3_byte_t *id3_parse_binary(id3_byte_t const **, id3_length_t);
-
-# endif
diff --git a/src/libid3tag/render.c b/src/libid3tag/render.c
deleted file mode 100644
index b699945..0000000
--- a/src/libid3tag/render.c
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: render.c,v 1.11 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <string.h>
-# include <stdlib.h>
-
-# ifdef HAVE_ASSERT_H
-# include <assert.h>
-# endif
-
-# include "id3tag.h"
-# include "render.h"
-# include "ucs4.h"
-# include "latin1.h"
-# include "utf16.h"
-# include "utf8.h"
-
-id3_length_t id3_render_immediate(id3_byte_t **ptr,
- char const *value, unsigned int bytes)
-{
- assert(value);
- assert(bytes == 8 || bytes == 4 || bytes == 3);
-
- if (ptr) {
- switch (bytes) {
- case 8: *(*ptr)++ = *value++;
- *(*ptr)++ = *value++;
- *(*ptr)++ = *value++;
- *(*ptr)++ = *value++;
- case 4: *(*ptr)++ = *value++;
- case 3: *(*ptr)++ = *value++;
- *(*ptr)++ = *value++;
- *(*ptr)++ = *value++;
- }
- }
-
- return bytes;
-}
-
-id3_length_t id3_render_syncsafe(id3_byte_t **ptr,
- unsigned long num, unsigned int bytes)
-{
- assert(bytes == 4 || bytes == 5);
-
- if (ptr) {
- switch (bytes) {
- case 5: *(*ptr)++ = (num >> 28) & 0x0f;
- case 4: *(*ptr)++ = (num >> 21) & 0x7f;
- *(*ptr)++ = (num >> 14) & 0x7f;
- *(*ptr)++ = (num >> 7) & 0x7f;
- *(*ptr)++ = (num >> 0) & 0x7f;
- }
- }
-
- return bytes;
-}
-
-id3_length_t id3_render_int(id3_byte_t **ptr,
- signed long num, unsigned int bytes)
-{
- assert(bytes >= 1 && bytes <= 4);
-
- if (ptr) {
- switch (bytes) {
- case 4: *(*ptr)++ = num >> 24;
- case 3: *(*ptr)++ = num >> 16;
- case 2: *(*ptr)++ = num >> 8;
- case 1: *(*ptr)++ = num >> 0;
- }
- }
-
- return bytes;
-}
-
-id3_length_t id3_render_binary(id3_byte_t **ptr,
- id3_byte_t const *data, id3_length_t length)
-{
- if (data == 0)
- return 0;
-
- if (ptr) {
- memcpy(*ptr, data, length);
- *ptr += length;
- }
-
- return length;
-}
-
-id3_length_t id3_render_latin1(id3_byte_t **ptr,
- id3_latin1_t const *latin1, int terminate)
-{
- id3_length_t size;
-
- if (latin1 == 0)
- latin1 = (id3_latin1_t *)"";
-
- size = id3_latin1_size(latin1);
- if (!terminate)
- --size;
-
- if (ptr) {
- memcpy(*ptr, latin1, size);
- *ptr += size;
- }
-
- return size;
-}
-
-id3_length_t id3_render_string(id3_byte_t **ptr, id3_ucs4_t const *ucs4,
- enum id3_field_textencoding encoding,
- int terminate)
-{
- enum id3_utf16_byteorder byteorder = ID3_UTF16_BYTEORDER_ANY;
-
- if (ucs4 == 0)
- ucs4 = id3_ucs4_empty;
-
- switch (encoding) {
- case ID3_FIELD_TEXTENCODING_ISO_8859_1:
- return id3_latin1_serialize(ptr, ucs4, terminate);
-
- case ID3_FIELD_TEXTENCODING_UTF_16BE:
- byteorder = ID3_UTF16_BYTEORDER_BE;
- case ID3_FIELD_TEXTENCODING_UTF_16:
- return id3_utf16_serialize(ptr, ucs4, byteorder, terminate);
-
- case ID3_FIELD_TEXTENCODING_UTF_8:
- return id3_utf8_serialize(ptr, ucs4, terminate);
- }
-
- return 0;
-}
-
-id3_length_t id3_render_padding(id3_byte_t **ptr, id3_byte_t value,
- id3_length_t length)
-{
- if (ptr) {
- memset(*ptr, value, length);
- *ptr += length;
- }
-
- return length;
-}
-
-/*
- * NAME: render->paddedstring()
- * DESCRIPTION: render a space-padded string using latin1 encoding
- */
-id3_length_t id3_render_paddedstring(id3_byte_t **ptr, id3_ucs4_t const *ucs4,
- id3_length_t length)
-{
- id3_ucs4_t padded[31], *data, *end;
-
- /* latin1 encoding only (this is used for ID3v1 fields) */
-
- assert(length <= 30);
-
- data = padded;
- end = data + length;
-
- if (ucs4) {
- while (*ucs4 && end - data > 0) {
- *data++ = *ucs4++;
-
- if (data[-1] == '\n')
- data[-1] = ' ';
- }
- }
-
- while (end - data > 0)
- *data++ = ' ';
-
- *data = 0;
-
- return id3_latin1_serialize(ptr, padded, 0);
-}
diff --git a/src/libid3tag/render.h b/src/libid3tag/render.h
deleted file mode 100644
index 702605d..0000000
--- a/src/libid3tag/render.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: render.h,v 1.7 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_RENDER_H
-# define LIBID3TAG_RENDER_H
-
-# include "id3tag.h"
-
-id3_length_t id3_render_immediate(id3_byte_t **, char const *, unsigned int);
-id3_length_t id3_render_syncsafe(id3_byte_t **, unsigned long, unsigned int);
-id3_length_t id3_render_int(id3_byte_t **, signed long, unsigned int);
-id3_length_t id3_render_binary(id3_byte_t **,
- id3_byte_t const *, id3_length_t);
-id3_length_t id3_render_latin1(id3_byte_t **, id3_latin1_t const *, int);
-id3_length_t id3_render_string(id3_byte_t **, id3_ucs4_t const *,
- enum id3_field_textencoding, int);
-id3_length_t id3_render_padding(id3_byte_t **, id3_byte_t, id3_length_t);
-
-id3_length_t id3_render_paddedstring(id3_byte_t **, id3_ucs4_t const *,
- id3_length_t);
-
-# endif
diff --git a/src/libid3tag/tag.c b/src/libid3tag/tag.c
deleted file mode 100644
index 0323355..0000000
--- a/src/libid3tag/tag.c
+++ /dev/null
@@ -1,912 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: tag.c,v 1.20 2004/02/17 02:04:10 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <string.h>
-# include <stdlib.h>
-
-# ifdef HAVE_ASSERT_H
-# include <assert.h>
-# endif
-
-# include "id3tag.h"
-# include "tag.h"
-# include "frame.h"
-# include "compat.h"
-# include "parse.h"
-# include "render.h"
-# include "latin1.h"
-# include "ucs4.h"
-# include "genre.h"
-# include "crc.h"
-# include "field.h"
-# include "util.h"
-
-/*
- * NAME: tag->new()
- * DESCRIPTION: allocate and return a new, empty tag
- */
-struct id3_tag *id3_tag_new(void)
-{
- struct id3_tag *tag;
-
- tag = malloc(sizeof(*tag));
- if (tag) {
- tag->refcount = 0;
- tag->version = ID3_TAG_VERSION;
- tag->flags = 0;
- tag->extendedflags = 0;
- tag->restrictions = 0;
- tag->options = /* ID3_TAG_OPTION_UNSYNCHRONISATION | */
- ID3_TAG_OPTION_COMPRESSION | ID3_TAG_OPTION_CRC;
- tag->nframes = 0;
- tag->frames = 0;
- tag->paddedsize = 0;
- }
-
- return tag;
-}
-
-/*
- * NAME: tag->delete()
- * DESCRIPTION: destroy a tag and deallocate all associated memory
- */
-void id3_tag_delete(struct id3_tag *tag)
-{
- assert(tag);
-
- if (tag->refcount == 0) {
- id3_tag_clearframes(tag);
-
- if (tag->frames)
- free(tag->frames);
-
- free(tag);
- }
-}
-
-/*
- * NAME: tag->addref()
- * DESCRIPTION: add an external reference to a tag
- */
-void id3_tag_addref(struct id3_tag *tag)
-{
- assert(tag);
-
- ++tag->refcount;
-}
-
-/*
- * NAME: tag->delref()
- * DESCRIPTION: remove an external reference to a tag
- */
-void id3_tag_delref(struct id3_tag *tag)
-{
- assert(tag && tag->refcount > 0);
-
- --tag->refcount;
-}
-
-/*
- * NAME: tag->version()
- * DESCRIPTION: return the tag's original ID3 version number
- */
-unsigned int id3_tag_version(struct id3_tag const *tag)
-{
- assert(tag);
-
- return tag->version;
-}
-
-/*
- * NAME: tag->options()
- * DESCRIPTION: get or set tag options
- */
-int id3_tag_options(struct id3_tag *tag, int mask, int values)
-{
- assert(tag);
-
- if (mask)
- tag->options = (tag->options & ~mask) | (values & mask);
-
- return tag->options;
-}
-
-/*
- * NAME: tag->setlength()
- * DESCRIPTION: set the minimum rendered tag size
- */
-void id3_tag_setlength(struct id3_tag *tag, id3_length_t length)
-{
- assert(tag);
-
- tag->paddedsize = length;
-}
-
-/*
- * NAME: tag->clearframes()
- * DESCRIPTION: detach and delete all frames associated with a tag
- */
-void id3_tag_clearframes(struct id3_tag *tag)
-{
- unsigned int i;
-
- assert(tag);
-
- for (i = 0; i < tag->nframes; ++i) {
- id3_frame_delref(tag->frames[i]);
- id3_frame_delete(tag->frames[i]);
- }
-
- tag->nframes = 0;
-}
-
-/*
- * NAME: tag->attachframe()
- * DESCRIPTION: attach a frame to a tag
- */
-int id3_tag_attachframe(struct id3_tag *tag, struct id3_frame *frame)
-{
- struct id3_frame **frames;
-
- assert(tag && frame);
-
- frames = realloc(tag->frames, (tag->nframes + 1) * sizeof(*frames));
- if (frames == 0)
- return -1;
-
- tag->frames = frames;
- tag->frames[tag->nframes++] = frame;
-
- id3_frame_addref(frame);
-
- return 0;
-}
-
-/*
- * NAME: tag->detachframe()
- * DESCRIPTION: detach (but don't delete) a frame from a tag
- */
-int id3_tag_detachframe(struct id3_tag *tag, struct id3_frame *frame)
-{
- unsigned int i;
-
- assert(tag && frame);
-
- for (i = 0; i < tag->nframes; ++i) {
- if (tag->frames[i] == frame)
- break;
- }
-
- if (i == tag->nframes)
- return -1;
-
- --tag->nframes;
- while (i++ < tag->nframes)
- tag->frames[i - 1] = tag->frames[i];
-
- id3_frame_delref(frame);
-
- return 0;
-}
-
-/*
- * NAME: tag->findframe()
- * DESCRIPTION: find in a tag the nth (0-based) frame with the given frame ID
- */
-struct id3_frame *id3_tag_findframe(struct id3_tag const *tag,
- char const *id, unsigned int index)
-{
- unsigned int len, i;
-
- assert(tag);
-
- if (id == 0 || *id == 0)
- return (index < tag->nframes) ? tag->frames[index] : 0;
-
- len = strlen(id);
-
- if (len == 4) {
- struct id3_compat const *compat;
-
- compat = id3_compat_lookup(id, len);
- if (compat && compat->equiv && !compat->translate) {
- id = compat->equiv;
- len = strlen(id);
- }
- }
-
- for (i = 0; i < tag->nframes; ++i) {
- if (strncmp(tag->frames[i]->id, id, len) == 0 && index-- == 0)
- return tag->frames[i];
- }
-
- return 0;
-}
-
-enum tagtype {
- TAGTYPE_NONE = 0,
- TAGTYPE_ID3V1,
- TAGTYPE_ID3V2,
- TAGTYPE_ID3V2_FOOTER
-};
-
-static
-enum tagtype tagtype(id3_byte_t const *data, id3_length_t length)
-{
- if (length >= 3 &&
- data[0] == 'T' && data[1] == 'A' && data[2] == 'G')
- return TAGTYPE_ID3V1;
-
- if (length >= 10 &&
- ((data[0] == 'I' && data[1] == 'D' && data[2] == '3') ||
- (data[0] == '3' && data[1] == 'D' && data[2] == 'I')) &&
- data[3] < 0xff && data[4] < 0xff &&
- data[6] < 0x80 && data[7] < 0x80 && data[8] < 0x80 && data[9] < 0x80)
- return data[0] == 'I' ? TAGTYPE_ID3V2 : TAGTYPE_ID3V2_FOOTER;
-
- return TAGTYPE_NONE;
-}
-
-static
-void parse_header(id3_byte_t const **ptr,
- unsigned int *version, int *flags, id3_length_t *size)
-{
- *ptr += 3;
-
- *version = id3_parse_uint(ptr, 2);
- *flags = id3_parse_uint(ptr, 1);
- *size = id3_parse_syncsafe(ptr, 4);
-}
-
-/*
- * NAME: tag->query()
- * DESCRIPTION: if a tag begins at the given location, return its size
- */
-signed long id3_tag_query(id3_byte_t const *data, id3_length_t length)
-{
- unsigned int version;
- int flags;
- id3_length_t size;
-
- assert(data);
-
- switch (tagtype(data, length)) {
- case TAGTYPE_ID3V1:
- return 128;
-
- case TAGTYPE_ID3V2:
- parse_header(&data, &version, &flags, &size);
-
- if (flags & ID3_TAG_FLAG_FOOTERPRESENT)
- size += 10;
-
- return 10 + size;
-
- case TAGTYPE_ID3V2_FOOTER:
- parse_header(&data, &version, &flags, &size);
- return -size - 10;
-
- case TAGTYPE_NONE:
- break;
- }
-
- return 0;
-}
-
-static
-void trim(char *str)
-{
- char *ptr;
-
- ptr = str + strlen(str);
- while (ptr > str && ptr[-1] == ' ')
- --ptr;
-
- *ptr = 0;
-}
-
-static
-int v1_attachstr(struct id3_tag *tag, char const *id,
- id3_byte_t *text, unsigned long number)
-{
- struct id3_frame *frame;
- id3_ucs4_t ucs4[31];
-
- if (text) {
- trim((char *)text);
- if (*text == 0)
- return 0;
- }
-
- frame = id3_frame_new(id);
- if (frame == 0)
- return -1;
-
- if (id3_field_settextencoding(&frame->fields[0],
- ID3_FIELD_TEXTENCODING_ISO_8859_1) == -1)
- goto fail;
-
- if (text)
- id3_latin1_decode((id3_latin1_t *)text, ucs4);
- else
- id3_ucs4_putnumber(ucs4, number);
-
- if (strcmp(id, ID3_FRAME_COMMENT) == 0) {
- if (id3_field_setlanguage(&frame->fields[1], "XXX") == -1 ||
- id3_field_setstring(&frame->fields[2], id3_ucs4_empty) == -1 ||
- id3_field_setfullstring(&frame->fields[3], ucs4) == -1)
- goto fail;
- }
- else {
- id3_ucs4_t *ptr = ucs4;
-
- if (id3_field_setstrings(&frame->fields[1], 1, &ptr) == -1)
- goto fail;
- }
-
- if (id3_tag_attachframe(tag, frame) == -1)
- goto fail;
-
- return 0;
-
- fail:
- id3_frame_delete(frame);
- return -1;
-}
-
-static
-struct id3_tag *v1_parse(id3_byte_t const *data)
-{
- struct id3_tag *tag;
-
- tag = id3_tag_new();
- if (tag) {
- id3_byte_t title[31], artist[31], album[31], year[5], comment[31];
- unsigned int genre, track;
-
- tag->version = 0x0100;
-
- tag->options |= ID3_TAG_OPTION_ID3V1;
- tag->options &= ~ID3_TAG_OPTION_COMPRESSION;
-
- tag->restrictions =
- ID3_TAG_RESTRICTION_TEXTENCODING_LATIN1_UTF8 |
- ID3_TAG_RESTRICTION_TEXTSIZE_30_CHARS;
-
- title[30] = artist[30] = album[30] = year[4] = comment[30] = 0;
-
- memcpy(title, &data[3], 30);
- memcpy(artist, &data[33], 30);
- memcpy(album, &data[63], 30);
- memcpy(year, &data[93], 4);
- memcpy(comment, &data[97], 30);
-
- genre = data[127];
-
- track = 0;
- if (comment[28] == 0 && comment[29] != 0) {
- track = comment[29];
- tag->version = 0x0101;
- }
-
- /* populate tag frames */
-
- if (v1_attachstr(tag, ID3_FRAME_TITLE, title, 0) == -1 ||
- v1_attachstr(tag, ID3_FRAME_ARTIST, artist, 0) == -1 ||
- v1_attachstr(tag, ID3_FRAME_ALBUM, album, 0) == -1 ||
- v1_attachstr(tag, ID3_FRAME_YEAR, year, 0) == -1 ||
- (track && v1_attachstr(tag, ID3_FRAME_TRACK, 0, track) == -1) ||
- (genre < 0xff && v1_attachstr(tag, ID3_FRAME_GENRE, 0, genre) == -1) ||
- v1_attachstr(tag, ID3_FRAME_COMMENT, comment, 0) == -1) {
- id3_tag_delete(tag);
- tag = 0;
- }
- }
-
- return tag;
-}
-
-static
-struct id3_tag *v2_parse(id3_byte_t const *ptr)
-{
- struct id3_tag *tag;
- id3_byte_t *mem = 0;
-
- tag = id3_tag_new();
- if (tag) {
- id3_byte_t const *end;
- id3_length_t size;
-
- parse_header(&ptr, &tag->version, &tag->flags, &size);
-
- tag->paddedsize = 10 + size;
-
- if ((tag->flags & ID3_TAG_FLAG_UNSYNCHRONISATION) &&
- ID3_TAG_VERSION_MAJOR(tag->version) < 4) {
- mem = malloc(size);
- if (mem == 0)
- goto fail;
-
- memcpy(mem, ptr, size);
-
- size = id3_util_deunsynchronise(mem, size);
- ptr = mem;
- }
-
- end = ptr + size;
-
- if (tag->flags & ID3_TAG_FLAG_EXTENDEDHEADER) {
- switch (ID3_TAG_VERSION_MAJOR(tag->version)) {
- case 2:
- goto fail;
-
- case 3:
- {
- id3_byte_t const *ehptr, *ehend;
- id3_length_t ehsize;
-
- enum {
- EH_FLAG_CRC = 0x8000 /* CRC data present */
- };
-
- if (end - ptr < 4)
- goto fail;
-
- ehsize = id3_parse_uint(&ptr, 4);
-
- if (ehsize > end - ptr)
- goto fail;
-
- ehptr = ptr;
- ehend = ptr + ehsize;
-
- ptr = ehend;
-
- if (ehend - ehptr >= 6) {
- int ehflags;
- id3_length_t padsize;
-
- ehflags = id3_parse_uint(&ehptr, 2);
- padsize = id3_parse_uint(&ehptr, 4);
-
- if (padsize > end - ptr)
- goto fail;
-
- end -= padsize;
-
- if (ehflags & EH_FLAG_CRC) {
- unsigned long crc;
-
- if (ehend - ehptr < 4)
- goto fail;
-
- crc = id3_parse_uint(&ehptr, 4);
-
- if (crc != id3_crc_compute(ptr, end - ptr))
- goto fail;
-
- tag->extendedflags |= ID3_TAG_EXTENDEDFLAG_CRCDATAPRESENT;
- }
- }
- }
- break;
-
- case 4:
- {
- id3_byte_t const *ehptr, *ehend;
- id3_length_t ehsize;
- unsigned int bytes;
-
- if (end - ptr < 4)
- goto fail;
-
- ehptr = ptr;
- ehsize = id3_parse_syncsafe(&ptr, 4);
-
- if (ehsize < 6 || ehsize > end - ehptr)
- goto fail;
-
- ehend = ehptr + ehsize;
-
- bytes = id3_parse_uint(&ptr, 1);
-
- if (bytes < 1 || bytes > ehend - ptr)
- goto fail;
-
- ehptr = ptr + bytes;
-
- /* verify extended header size */
- {
- id3_byte_t const *flagsptr = ptr, *dataptr = ehptr;
- unsigned int datalen;
- int ehflags;
-
- while (bytes--) {
- for (ehflags = id3_parse_uint(&flagsptr, 1); ehflags;
- ehflags = (ehflags << 1) & 0xff) {
- if (ehflags & 0x80) {
- if (dataptr == ehend)
- goto fail;
- datalen = id3_parse_uint(&dataptr, 1);
- if (datalen > 0x7f || datalen > ehend - dataptr)
- goto fail;
- dataptr += datalen;
- }
- }
- }
- }
-
- tag->extendedflags = id3_parse_uint(&ptr, 1);
-
- ptr = ehend;
-
- if (tag->extendedflags & ID3_TAG_EXTENDEDFLAG_TAGISANUPDATE) {
- bytes = id3_parse_uint(&ehptr, 1);
- ehptr += bytes;
- }
-
- if (tag->extendedflags & ID3_TAG_EXTENDEDFLAG_CRCDATAPRESENT) {
- unsigned long crc;
-
- bytes = id3_parse_uint(&ehptr, 1);
- if (bytes < 5)
- goto fail;
-
- crc = id3_parse_syncsafe(&ehptr, 5);
- ehptr += bytes - 5;
-
- if (crc != id3_crc_compute(ptr, end - ptr))
- goto fail;
- }
-
- if (tag->extendedflags & ID3_TAG_EXTENDEDFLAG_TAGRESTRICTIONS) {
- bytes = id3_parse_uint(&ehptr, 1);
- if (bytes < 1)
- goto fail;
-
- tag->restrictions = id3_parse_uint(&ehptr, 1);
- ehptr += bytes - 1;
- }
- }
- break;
- }
- }
-
- /* frames */
-
- while (ptr < end) {
- struct id3_frame *frame;
-
- if (*ptr == 0)
- break; /* padding */
-
- frame = id3_frame_parse(&ptr, end - ptr, tag->version);
- if (frame == 0 || id3_tag_attachframe(tag, frame) == -1)
- goto fail;
- }
-
- if (ID3_TAG_VERSION_MAJOR(tag->version) < 4 &&
- id3_compat_fixup(tag) == -1)
- goto fail;
- }
-
- if (0) {
- fail:
- id3_tag_delete(tag);
- tag = 0;
- }
-
- if (mem)
- free(mem);
-
- return tag;
-}
-
-/*
- * NAME: tag->parse()
- * DESCRIPTION: parse a complete ID3 tag
- */
-struct id3_tag *id3_tag_parse(id3_byte_t const *data, id3_length_t length)
-{
- id3_byte_t const *ptr;
- unsigned int version;
- int flags;
- id3_length_t size;
-
- assert(data);
-
- switch (tagtype(data, length)) {
- case TAGTYPE_ID3V1:
- return (length < 128) ? 0 : v1_parse(data);
-
- case TAGTYPE_ID3V2:
- break;
-
- case TAGTYPE_ID3V2_FOOTER:
- case TAGTYPE_NONE:
- return 0;
- }
-
- /* ID3v2.x */
-
- ptr = data;
- parse_header(&ptr, &version, &flags, &size);
-
- switch (ID3_TAG_VERSION_MAJOR(version)) {
- case 4:
- if (flags & ID3_TAG_FLAG_FOOTERPRESENT)
- size += 10;
- case 2:
- case 3:
- return (length < 10 + size) ? 0 : v2_parse(data);
- }
-
- return 0;
-}
-
-static
-void v1_renderstr(struct id3_tag const *tag, char const *frameid,
- id3_byte_t **buffer, id3_length_t length)
-{
- struct id3_frame *frame;
- id3_ucs4_t const *string;
-
- frame = id3_tag_findframe(tag, frameid, 0);
- if (frame == 0)
- string = id3_ucs4_empty;
- else {
- if (strcmp(frameid, ID3_FRAME_COMMENT) == 0)
- string = id3_field_getfullstring(&frame->fields[3]);
- else
- string = id3_field_getstrings(&frame->fields[1], 0);
- }
-
- id3_render_paddedstring(buffer, string, length);
-}
-
-/*
- * NAME: v1->render()
- * DESCRIPTION: render an ID3v1 (or ID3v1.1) tag
- */
-static
-id3_length_t v1_render(struct id3_tag const *tag, id3_byte_t *buffer)
-{
- id3_byte_t data[128], *ptr;
- struct id3_frame *frame;
- unsigned int i;
- int genre = -1;
-
- ptr = data;
-
- id3_render_immediate(&ptr, "TAG", 3);
-
- v1_renderstr(tag, ID3_FRAME_TITLE, &ptr, 30);
- v1_renderstr(tag, ID3_FRAME_ARTIST, &ptr, 30);
- v1_renderstr(tag, ID3_FRAME_ALBUM, &ptr, 30);
- v1_renderstr(tag, ID3_FRAME_YEAR, &ptr, 4);
- v1_renderstr(tag, ID3_FRAME_COMMENT, &ptr, 30);
-
- /* ID3v1.1 track number */
-
- frame = id3_tag_findframe(tag, ID3_FRAME_TRACK, 0);
- if (frame) {
- id3_ucs4_t const *string;
- unsigned int track = 0;
-
- string = id3_field_getstrings(&frame->fields[1], 0);
- if (string)
- track = id3_ucs4_getnumber(string);
- if (track > 0 && track <= 0xff) {
- ptr[-2] = 0;
- ptr[-1] = track;
- }
- }
-
- /* ID3v1 genre number */
-
- frame = id3_tag_findframe(tag, ID3_FRAME_GENRE, 0);
- if (frame) {
- unsigned int nstrings;
-
- nstrings = id3_field_getnstrings(&frame->fields[1]);
-
- for (i = 0; i < nstrings; ++i) {
- genre = id3_genre_number(id3_field_getstrings(&frame->fields[1], i));
- if (genre != -1)
- break;
- }
-
- if (i == nstrings && nstrings > 0)
- genre = ID3_GENRE_OTHER;
- }
-
- id3_render_int(&ptr, genre, 1);
-
- /* make sure the tag is not empty */
-
- if (genre == -1) {
- for (i = 3; i < 127; ++i) {
- if (data[i] != ' ')
- break;
- }
-
- if (i == 127)
- return 0;
- }
-
- if (buffer)
- memcpy(buffer, data, 128);
-
- return 128;
-}
-
-/*
- * NAME: tag->render()
- * DESCRIPTION: render a complete ID3 tag
- */
-id3_length_t id3_tag_render(struct id3_tag const *tag, id3_byte_t *buffer)
-{
- id3_length_t size = 0;
- id3_byte_t **ptr,
- *header_ptr = 0, *tagsize_ptr = 0, *crc_ptr = 0, *frames_ptr = 0;
- int flags, extendedflags;
- unsigned int i;
-
- assert(tag);
-
- if (tag->options & ID3_TAG_OPTION_ID3V1)
- return v1_render(tag, buffer);
-
- /* a tag must contain at least one (renderable) frame */
-
- for (i = 0; i < tag->nframes; ++i) {
- if (id3_frame_render(tag->frames[i], 0, 0) > 0)
- break;
- }
-
- if (i == tag->nframes)
- return 0;
-
- ptr = buffer ? &buffer : 0;
-
- /* get flags */
-
- flags = tag->flags & ID3_TAG_FLAG_KNOWNFLAGS;
- extendedflags = tag->extendedflags & ID3_TAG_EXTENDEDFLAG_KNOWNFLAGS;
-
- extendedflags &= ~ID3_TAG_EXTENDEDFLAG_CRCDATAPRESENT;
- if (tag->options & ID3_TAG_OPTION_CRC)
- extendedflags |= ID3_TAG_EXTENDEDFLAG_CRCDATAPRESENT;
-
- extendedflags &= ~ID3_TAG_EXTENDEDFLAG_TAGRESTRICTIONS;
- if (tag->restrictions)
- extendedflags |= ID3_TAG_EXTENDEDFLAG_TAGRESTRICTIONS;
-
- flags &= ~ID3_TAG_FLAG_UNSYNCHRONISATION;
- if (tag->options & ID3_TAG_OPTION_UNSYNCHRONISATION)
- flags |= ID3_TAG_FLAG_UNSYNCHRONISATION;
-
- flags &= ~ID3_TAG_FLAG_EXTENDEDHEADER;
- if (extendedflags)
- flags |= ID3_TAG_FLAG_EXTENDEDHEADER;
-
- flags &= ~ID3_TAG_FLAG_FOOTERPRESENT;
- if (tag->options & ID3_TAG_OPTION_APPENDEDTAG)
- flags |= ID3_TAG_FLAG_FOOTERPRESENT;
-
- /* header */
-
- if (ptr)
- header_ptr = *ptr;
-
- size += id3_render_immediate(ptr, "ID3", 3);
- size += id3_render_int(ptr, ID3_TAG_VERSION, 2);
- size += id3_render_int(ptr, flags, 1);
-
- if (ptr)
- tagsize_ptr = *ptr;
-
- size += id3_render_syncsafe(ptr, 0, 4);
-
- /* extended header */
-
- if (flags & ID3_TAG_FLAG_EXTENDEDHEADER) {
- id3_length_t ehsize = 0;
- id3_byte_t *ehsize_ptr = 0;
-
- if (ptr)
- ehsize_ptr = *ptr;
-
- ehsize += id3_render_syncsafe(ptr, 0, 4);
- ehsize += id3_render_int(ptr, 1, 1);
- ehsize += id3_render_int(ptr, extendedflags, 1);
-
- if (extendedflags & ID3_TAG_EXTENDEDFLAG_TAGISANUPDATE)
- ehsize += id3_render_int(ptr, 0, 1);
-
- if (extendedflags & ID3_TAG_EXTENDEDFLAG_CRCDATAPRESENT) {
- ehsize += id3_render_int(ptr, 5, 1);
-
- if (ptr)
- crc_ptr = *ptr;
-
- ehsize += id3_render_syncsafe(ptr, 0, 5);
- }
-
- if (extendedflags & ID3_TAG_EXTENDEDFLAG_TAGRESTRICTIONS) {
- ehsize += id3_render_int(ptr, 1, 1);
- ehsize += id3_render_int(ptr, tag->restrictions, 1);
- }
-
- if (ehsize_ptr)
- id3_render_syncsafe(&ehsize_ptr, ehsize, 4);
-
- size += ehsize;
- }
-
- /* frames */
-
- if (ptr)
- frames_ptr = *ptr;
-
- for (i = 0; i < tag->nframes; ++i)
- size += id3_frame_render(tag->frames[i], ptr, tag->options);
-
- /* padding */
-
- if (!(flags & ID3_TAG_FLAG_FOOTERPRESENT)) {
- if (size < tag->paddedsize)
- size += id3_render_padding(ptr, 0, tag->paddedsize - size);
- else if (tag->options & ID3_TAG_OPTION_UNSYNCHRONISATION) {
- if (ptr == 0)
- size += 1;
- else {
- if ((*ptr)[-1] == 0xff)
- size += id3_render_padding(ptr, 0, 1);
- }
- }
- }
-
- /* patch tag size and CRC */
-
- if (tagsize_ptr)
- id3_render_syncsafe(&tagsize_ptr, size - 10, 4);
-
- if (crc_ptr) {
- id3_render_syncsafe(&crc_ptr,
- id3_crc_compute(frames_ptr, *ptr - frames_ptr), 5);
- }
-
- /* footer */
-
- if (flags & ID3_TAG_FLAG_FOOTERPRESENT) {
- size += id3_render_immediate(ptr, "3DI", 3);
- size += id3_render_binary(ptr, header_ptr + 3, 7);
- }
-
- return size;
-}
diff --git a/src/libid3tag/tag.h b/src/libid3tag/tag.h
deleted file mode 100644
index 2ce84d7..0000000
--- a/src/libid3tag/tag.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: tag.h,v 1.10 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_TAG_H
-# define LIBID3TAG_TAG_H
-
-# include "id3tag.h"
-
-void id3_tag_addref(struct id3_tag *);
-void id3_tag_delref(struct id3_tag *);
-
-# endif
diff --git a/src/libid3tag/ucs4.c b/src/libid3tag/ucs4.c
deleted file mode 100644
index 56a587d..0000000
--- a/src/libid3tag/ucs4.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: ucs4.c,v 1.13 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <stdlib.h>
-
-# include "id3tag.h"
-# include "ucs4.h"
-# include "latin1.h"
-# include "utf16.h"
-# include "utf8.h"
-
-id3_ucs4_t const id3_ucs4_empty[] = { 0 };
-
-/*
- * NAME: ucs4->length()
- * DESCRIPTION: return the number of ucs4 chars represented by a ucs4 string
- */
-id3_length_t id3_ucs4_length(id3_ucs4_t const *ucs4)
-{
- id3_ucs4_t const *ptr = ucs4;
-
- while (*ptr)
- ++ptr;
-
- return ptr - ucs4;
-}
-
-/*
- * NAME: ucs4->size()
- * DESCRIPTION: return the encoding size of a ucs4 string
- */
-id3_length_t id3_ucs4_size(id3_ucs4_t const *ucs4)
-{
- return id3_ucs4_length(ucs4) + 1;
-}
-
-/*
- * NAME: ucs4->latin1size()
- * DESCRIPTION: return the encoding size of a latin1-encoded ucs4 string
- */
-id3_length_t id3_ucs4_latin1size(id3_ucs4_t const *ucs4)
-{
- return id3_ucs4_size(ucs4);
-}
-
-/*
- * NAME: ucs4->utf16size()
- * DESCRIPTION: return the encoding size of a utf16-encoded ucs4 string
- */
-id3_length_t id3_ucs4_utf16size(id3_ucs4_t const *ucs4)
-{
- id3_length_t size = 0;
-
- while (*ucs4) {
- ++size;
- if (*ucs4 >= 0x00010000L &&
- *ucs4 <= 0x0010ffffL)
- ++size;
-
- ++ucs4;
- }
-
- return size + 1;
-}
-
-/*
- * NAME: ucs4->utf8size()
- * DESCRIPTION: return the encoding size of a utf8-encoded ucs4 string
- */
-id3_length_t id3_ucs4_utf8size(id3_ucs4_t const *ucs4)
-{
- id3_length_t size = 0;
-
- while (*ucs4) {
- if (*ucs4 <= 0x0000007fL)
- size += 1;
- else if (*ucs4 <= 0x000007ffL)
- size += 2;
- else if (*ucs4 <= 0x0000ffffL)
- size += 3;
- else if (*ucs4 <= 0x001fffffL)
- size += 4;
- else if (*ucs4 <= 0x03ffffffL)
- size += 5;
- else if (*ucs4 <= 0x7fffffffL)
- size += 6;
- else
- size += 2; /* based on U+00B7 replacement char */
-
- ++ucs4;
- }
-
- return size + 1;
-}
-
-/*
- * NAME: ucs4->utf8size()
- * DESCRIPTION: return the encoding size of a utf8-encoded ucs4 string
- */
-id3_length_t id3_ucs4_multibytesize(id3_ucs4_t const *ucs4)
-{
- id3_length_t size = 0;
-
- while (*ucs4) {
- if (*ucs4 <= 0x0000007fL)
- size += 1;
- else if (*ucs4 <= 0x000007ffL)
- size += 2;
- else if (*ucs4 <= 0x0000ffffL)
- size += 3;
- else if (*ucs4 <= 0x001fffffL)
- size += 4;
- else if (*ucs4 <= 0x03ffffffL)
- size += 5;
- else if (*ucs4 <= 0x7fffffffL)
- size += 6;
- else
- size += 2; /* based on U+00B7 replacement char */
-
- ++ucs4;
- }
-
- return size + 1;
-}
-
-/*
- * NAME: ucs4->latin1duplicate()
- * DESCRIPTION: duplicate and encode a ucs4 string into latin1
- */
-id3_latin1_t *id3_ucs4_latin1duplicate(id3_ucs4_t const *ucs4)
-{
- id3_latin1_t *latin1;
-
- latin1 = malloc(id3_ucs4_latin1size(ucs4) * sizeof(*latin1));
- if (latin1)
- id3_latin1_encode(latin1, ucs4);
-
- return release(latin1);
-}
-
-/*
- * NAME: ucs4->utf16duplicate()
- * DESCRIPTION: duplicate and encode a ucs4 string into utf16
- */
-id3_utf16_t *id3_ucs4_utf16duplicate(id3_ucs4_t const *ucs4)
-{
- id3_utf16_t *utf16;
-
- utf16 = malloc(id3_ucs4_utf16size(ucs4) * sizeof(*utf16));
- if (utf16)
- id3_utf16_encode(utf16, ucs4);
-
- return release(utf16);
-}
-
-/*
- * NAME: ucs4->utf8duplicate()
- * DESCRIPTION: duplicate and encode a ucs4 string into utf8
- */
-id3_utf8_t *id3_ucs4_utf8duplicate(id3_ucs4_t const *ucs4)
-{
- id3_utf8_t *utf8;
-
- utf8 = malloc(id3_ucs4_utf8size(ucs4) * sizeof(*utf8));
- if (utf8)
- id3_utf8_encode(utf8, ucs4);
-
- return release(utf8);
-}
-
-#if 0
-void id3_multibyte_encode(id3_latin1_t *multi, id3_ucs4_t const *ucs4)
-{
- id3_latin1_t *mptr;
- id3_ucs4_t *uptr;
- int multi
- //prescan
-
- // 1. if threre is multi byte entry, the string must be multi byte unicode string.
- // -> convert into utf-8
- // 2. if thre is no multi byte entry and there is a single byte character
-
- the string is in locale specific encoding or
-
- if(*uptr <
-
- *mptr =
-
-
-}
-
-/*
- * NAME: ucs4->utf8duplicate()
- * DESCRIPTION: duplicate and encode a ucs4 string into utf8
- */
-id3_utf8_t *id3_ucs4_multibyteduplicate(id3_ucs4_t const *ucs4)
-{
- id3_latin1_t *multi;
- multi = malloc(id3_ucs4_multibytesize(ucs4) * sizeof(*utf8));
- if (multi)
- id3_multibyte_encode(multi, ucs4);
-
- return release(multi);
-}
-#endif
-
-/*
- * NAME: ucs4->copy()
- * DESCRIPTION: copy a ucs4 string
- */
-void id3_ucs4_copy(id3_ucs4_t *dest, id3_ucs4_t const *src)
-{
- while ((*dest++ = *src++))
- ;
-}
-
-/*
- * NAME: ucs4->duplicate()
- * DESCRIPTION: duplicate a ucs4 string
- */
-id3_ucs4_t *id3_ucs4_duplicate(id3_ucs4_t const *src)
-{
- id3_ucs4_t *ucs4;
-
- ucs4 = malloc(id3_ucs4_size(src) * sizeof(*ucs4));
- if (ucs4)
- id3_ucs4_copy(ucs4, src);
-
- return ucs4;
-}
-
-/*
- * NAME: ucs4->putnumber()
- * DESCRIPTION: write a ucs4 string containing a (positive) decimal number
- */
-void id3_ucs4_putnumber(id3_ucs4_t *ucs4, unsigned long number)
-{
- int digits[10], *digit;
-
- digit = digits;
-
- do {
- *digit++ = number % 10;
- number /= 10;
- }
- while (number);
-
- while (digit != digits)
- *ucs4++ = '0' + *--digit;
-
- *ucs4 = 0;
-}
-
-/*
- * NAME: ucs4->getnumber()
- * DESCRIPTION: read a ucs4 string containing a (positive) decimal number
- */
-unsigned long id3_ucs4_getnumber(id3_ucs4_t const *ucs4)
-{
- unsigned long number = 0;
-
- while (*ucs4 >= '0' && *ucs4 <= '9')
- number = 10 * number + (*ucs4++ - '0');
-
- return number;
-}
diff --git a/src/libid3tag/ucs4.h b/src/libid3tag/ucs4.h
deleted file mode 100644
index bfb325d..0000000
--- a/src/libid3tag/ucs4.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: ucs4.h,v 1.11 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_UCS4_H
-# define LIBID3TAG_UCS4_H
-
-# include "id3tag.h"
-
-# define ID3_UCS4_REPLACEMENTCHAR 0x000000b7L /* middle dot */
-
-extern id3_ucs4_t const id3_ucs4_empty[];
-
-id3_length_t id3_ucs4_length(id3_ucs4_t const *);
-id3_length_t id3_ucs4_size(id3_ucs4_t const *);
-
-id3_length_t id3_ucs4_latin1size(id3_ucs4_t const *);
-id3_length_t id3_ucs4_utf16size(id3_ucs4_t const *);
-id3_length_t id3_ucs4_utf8size(id3_ucs4_t const *);
-
-void id3_ucs4_copy(id3_ucs4_t *, id3_ucs4_t const *);
-id3_ucs4_t *id3_ucs4_duplicate(id3_ucs4_t const *);
-
-# endif
diff --git a/src/libid3tag/utf16.c b/src/libid3tag/utf16.c
deleted file mode 100644
index 70ee9d5..0000000
--- a/src/libid3tag/utf16.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: utf16.c,v 1.9 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <stdlib.h>
-
-# include "id3tag.h"
-# include "utf16.h"
-# include "ucs4.h"
-
-/*
- * NAME: utf16->length()
- * DESCRIPTION: return the number of ucs4 chars represented by a utf16 string
- */
-id3_length_t id3_utf16_length(id3_utf16_t const *utf16)
-{
- id3_length_t length = 0;
-
- while (*utf16) {
- if (utf16[0] < 0xd800 || utf16[0] > 0xdfff)
- ++length;
- else if (utf16[0] >= 0xd800 && utf16[0] <= 0xdbff &&
- utf16[1] >= 0xdc00 && utf16[1] <= 0xdfff) {
- ++length;
- ++utf16;
- }
-
- ++utf16;
- }
-
- return length;
-}
-
-/*
- * NAME: utf16->size()
- * DESCRIPTION: return the encoding size of a utf16 string
- */
-id3_length_t id3_utf16_size(id3_utf16_t const *utf16)
-{
- id3_utf16_t const *ptr = utf16;
-
- while (*ptr)
- ++ptr;
-
- return ptr - utf16 + 1;
-}
-
-/*
- * NAME: utf16->ucs4duplicate()
- * DESCRIPTION: duplicate and decode a utf16 string into ucs4
- */
-id3_ucs4_t *id3_utf16_ucs4duplicate(id3_utf16_t const *utf16)
-{
- id3_ucs4_t *ucs4;
-
- ucs4 = malloc((id3_utf16_length(utf16) + 1) * sizeof(*ucs4));
- if (ucs4)
- id3_utf16_decode(utf16, ucs4);
-
- return release(ucs4);
-}
-
-/*
- * NAME: utf16->decodechar()
- * DESCRIPTION: decode a series of utf16 chars into a single ucs4 char
- */
-id3_length_t id3_utf16_decodechar(id3_utf16_t const *utf16, id3_ucs4_t *ucs4)
-{
- id3_utf16_t const *start = utf16;
-
- while (1) {
- if (utf16[0] < 0xd800 || utf16[0] > 0xdfff) {
- *ucs4 = utf16[0];
- return utf16 - start + 1;
- }
- else if (utf16[0] >= 0xd800 && utf16[0] <= 0xdbff &&
- utf16[1] >= 0xdc00 && utf16[1] <= 0xdfff) {
- *ucs4 = (((utf16[0] & 0x03ffL) << 10) |
- ((utf16[1] & 0x03ffL) << 0)) + 0x00010000L;
- return utf16 - start + 2;
- }
-
- ++utf16;
- }
-}
-
-/*
- * NAME: utf16->encodechar()
- * DESCRIPTION: encode a single ucs4 char into a series of up to 2 utf16 chars
- */
-id3_length_t id3_utf16_encodechar(id3_utf16_t *utf16, id3_ucs4_t ucs4)
-{
- if (ucs4 < 0x00010000L) {
- utf16[0] = ucs4;
-
- return 1;
- }
- else if (ucs4 < 0x00110000L) {
- ucs4 -= 0x00010000L;
-
- utf16[0] = ((ucs4 >> 10) & 0x3ff) | 0xd800;
- utf16[1] = ((ucs4 >> 0) & 0x3ff) | 0xdc00;
-
- return 2;
- }
-
- /* default */
-
- return id3_utf16_encodechar(utf16, ID3_UCS4_REPLACEMENTCHAR);
-}
-
-/*
- * NAME: utf16->decode()
- * DESCRIPTION: decode a complete utf16 string into a ucs4 string
- */
-void id3_utf16_decode(id3_utf16_t const *utf16, id3_ucs4_t *ucs4)
-{
- do
- utf16 += id3_utf16_decodechar(utf16, ucs4);
- while (*ucs4++);
-}
-
-/*
- * NAME: utf16->encode()
- * DESCRIPTION: encode a complete ucs4 string into a utf16 string
- */
-void id3_utf16_encode(id3_utf16_t *utf16, id3_ucs4_t const *ucs4)
-{
- do
- utf16 += id3_utf16_encodechar(utf16, *ucs4);
- while (*ucs4++);
-}
-
-/*
- * NAME: utf16->put()
- * DESCRIPTION: serialize a single utf16 character
- */
-id3_length_t id3_utf16_put(id3_byte_t **ptr, id3_utf16_t utf16,
- enum id3_utf16_byteorder byteorder)
-{
- if (ptr) {
- switch (byteorder) {
- default:
- case ID3_UTF16_BYTEORDER_BE:
- (*ptr)[0] = (utf16 >> 8) & 0xff;
- (*ptr)[1] = (utf16 >> 0) & 0xff;
- break;
-
- case ID3_UTF16_BYTEORDER_LE:
- (*ptr)[0] = (utf16 >> 0) & 0xff;
- (*ptr)[1] = (utf16 >> 8) & 0xff;
- break;
- }
-
- *ptr += 2;
- }
-
- return 2;
-}
-
-/*
- * NAME: utf16->get()
- * DESCRIPTION: deserialize a single utf16 character
- */
-id3_utf16_t id3_utf16_get(id3_byte_t const **ptr,
- enum id3_utf16_byteorder byteorder)
-{
- id3_utf16_t utf16;
-
- switch (byteorder) {
- default:
- case ID3_UTF16_BYTEORDER_BE:
- utf16 =
- ((*ptr)[0] << 8) |
- ((*ptr)[1] << 0);
- break;
-
- case ID3_UTF16_BYTEORDER_LE:
- utf16 =
- ((*ptr)[0] << 0) |
- ((*ptr)[1] << 8);
- break;
- }
-
- *ptr += 2;
-
- return utf16;
-}
-
-/*
- * NAME: utf16->serialize()
- * DESCRIPTION: serialize a ucs4 string using utf16 encoding
- */
-id3_length_t id3_utf16_serialize(id3_byte_t **ptr, id3_ucs4_t const *ucs4,
- enum id3_utf16_byteorder byteorder,
- int terminate)
-{
- id3_length_t size = 0;
- id3_utf16_t utf16[2], *out;
-
- if (byteorder == ID3_UTF16_BYTEORDER_ANY)
- size += id3_utf16_put(ptr, 0xfeff, byteorder);
-
- while (*ucs4) {
- switch (id3_utf16_encodechar(out = utf16, *ucs4++)) {
- case 2: size += id3_utf16_put(ptr, *out++, byteorder);
- case 1: size += id3_utf16_put(ptr, *out++, byteorder);
- case 0: break;
- }
- }
-
- if (terminate)
- size += id3_utf16_put(ptr, 0, byteorder);
-
- return size;
-}
-
-/*
- * NAME: utf16->deserialize()
- * DESCRIPTION: deserialize a ucs4 string using utf16 encoding
- */
-id3_ucs4_t *id3_utf16_deserialize(id3_byte_t const **ptr, id3_length_t length,
- enum id3_utf16_byteorder byteorder)
-{
- id3_byte_t const *end;
- id3_utf16_t *utf16ptr, *utf16;
- id3_ucs4_t *ucs4;
-
- end = *ptr + (length & ~1);
-
- utf16 = malloc((length / 2 + 1) * sizeof(*utf16));
- if (utf16 == 0)
- return 0;
-
- if (byteorder == ID3_UTF16_BYTEORDER_ANY && end - *ptr > 0) {
- switch (((*ptr)[0] << 8) |
- ((*ptr)[1] << 0)) {
- case 0xfeff:
- byteorder = ID3_UTF16_BYTEORDER_BE;
- *ptr += 2;
- break;
-
- case 0xfffe:
- byteorder = ID3_UTF16_BYTEORDER_LE;
- *ptr += 2;
- break;
- }
- }
-
- utf16ptr = utf16;
- while (end - *ptr > 0 && (*utf16ptr = id3_utf16_get(ptr, byteorder)))
- ++utf16ptr;
-
- *utf16ptr = 0;
-
- ucs4 = malloc((id3_utf16_length(utf16) + 1) * sizeof(*ucs4));
- if (ucs4)
- id3_utf16_decode(utf16, ucs4);
-
- free(utf16);
-
- return ucs4;
-}
diff --git a/src/libid3tag/utf16.h b/src/libid3tag/utf16.h
deleted file mode 100644
index b7be49c..0000000
--- a/src/libid3tag/utf16.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: utf16.h,v 1.8 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_UTF16_H
-# define LIBID3TAG_UTF16_H
-
-# include "id3tag.h"
-
-enum id3_utf16_byteorder {
- ID3_UTF16_BYTEORDER_ANY,
- ID3_UTF16_BYTEORDER_BE,
- ID3_UTF16_BYTEORDER_LE
-};
-
-id3_length_t id3_utf16_length(id3_utf16_t const *);
-id3_length_t id3_utf16_size(id3_utf16_t const *);
-
-id3_length_t id3_utf16_decodechar(id3_utf16_t const *, id3_ucs4_t *);
-id3_length_t id3_utf16_encodechar(id3_utf16_t *, id3_ucs4_t);
-
-void id3_utf16_decode(id3_utf16_t const *, id3_ucs4_t *);
-void id3_utf16_encode(id3_utf16_t *, id3_ucs4_t const *);
-
-id3_length_t id3_utf16_put(id3_byte_t **, id3_utf16_t,
- enum id3_utf16_byteorder);
-id3_utf16_t id3_utf16_get(id3_byte_t const **, enum id3_utf16_byteorder);
-
-id3_length_t id3_utf16_serialize(id3_byte_t **, id3_ucs4_t const *,
- enum id3_utf16_byteorder, int);
-id3_ucs4_t *id3_utf16_deserialize(id3_byte_t const **, id3_length_t,
- enum id3_utf16_byteorder);
-
-# endif
diff --git a/src/libid3tag/utf8.c b/src/libid3tag/utf8.c
deleted file mode 100644
index 4d8649a..0000000
--- a/src/libid3tag/utf8.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: utf8.c,v 1.9 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <stdlib.h>
-
-# include "id3tag.h"
-# include "utf8.h"
-# include "ucs4.h"
-
-/*
- * NAME: utf8->length()
- * DESCRIPTION: return the number of ucs4 chars represented by a utf8 string
- */
-id3_length_t id3_utf8_length(id3_utf8_t const *utf8)
-{
- id3_length_t length = 0;
-
- while (*utf8) {
- if ((utf8[0] & 0x80) == 0x00)
- ++length;
- else if ((utf8[0] & 0xe0) == 0xc0 &&
- (utf8[1] & 0xc0) == 0x80) {
- if (((utf8[0] & 0x1fL) << 6) >= 0x00000080L) {
- ++length;
- utf8 += 1;
- }
- }
- else if ((utf8[0] & 0xf0) == 0xe0 &&
- (utf8[1] & 0xc0) == 0x80 &&
- (utf8[2] & 0xc0) == 0x80) {
- if ((((utf8[0] & 0x0fL) << 12) |
- ((utf8[1] & 0x3fL) << 6)) >= 0x00000800L) {
- ++length;
- utf8 += 2;
- }
- }
- else if ((utf8[0] & 0xf8) == 0xf0 &&
- (utf8[1] & 0xc0) == 0x80 &&
- (utf8[2] & 0xc0) == 0x80 &&
- (utf8[3] & 0xc0) == 0x80) {
- if ((((utf8[0] & 0x07L) << 18) |
- ((utf8[1] & 0x3fL) << 12)) >= 0x00010000L) {
- ++length;
- utf8 += 3;
- }
- }
- else if ((utf8[0] & 0xfc) == 0xf8 &&
- (utf8[1] & 0xc0) == 0x80 &&
- (utf8[2] & 0xc0) == 0x80 &&
- (utf8[3] & 0xc0) == 0x80 &&
- (utf8[4] & 0xc0) == 0x80) {
- if ((((utf8[0] & 0x03L) << 24) |
- ((utf8[0] & 0x3fL) << 18)) >= 0x00200000L) {
- ++length;
- utf8 += 4;
- }
- }
- else if ((utf8[0] & 0xfe) == 0xfc &&
- (utf8[1] & 0xc0) == 0x80 &&
- (utf8[2] & 0xc0) == 0x80 &&
- (utf8[3] & 0xc0) == 0x80 &&
- (utf8[4] & 0xc0) == 0x80 &&
- (utf8[5] & 0xc0) == 0x80) {
- if ((((utf8[0] & 0x01L) << 30) |
- ((utf8[0] & 0x3fL) << 24)) >= 0x04000000L) {
- ++length;
- utf8 += 5;
- }
- }
-
- ++utf8;
- }
-
- return length;
-}
-
-/*
- * NAME: utf8->size()
- * DESCRIPTION: return the encoding size of a utf8 string
- */
-id3_length_t id3_utf8_size(id3_utf8_t const *utf8)
-{
- id3_utf8_t const *ptr = utf8;
-
- while (*ptr)
- ++ptr;
-
- return ptr - utf8 + 1;
-}
-
-/*
- * NAME: utf8->ucs4duplicate()
- * DESCRIPTION: duplicate and decode a utf8 string into ucs4
- */
-id3_ucs4_t *id3_utf8_ucs4duplicate(id3_utf8_t const *utf8)
-{
- id3_ucs4_t *ucs4;
-
- ucs4 = malloc((id3_utf8_length(utf8) + 1) * sizeof(*ucs4));
- if (ucs4)
- id3_utf8_decode(utf8, ucs4);
-
- return release(ucs4);
-}
-
-/*
- * NAME: utf8->decodechar()
- * DESCRIPTION: decode a series of utf8 chars into a single ucs4 char
- */
-id3_length_t id3_utf8_decodechar(id3_utf8_t const *utf8, id3_ucs4_t *ucs4)
-{
- id3_utf8_t const *start = utf8;
-
- while (1) {
- if ((utf8[0] & 0x80) == 0x00) {
- *ucs4 = utf8[0];
- return utf8 - start + 1;
- }
- else if ((utf8[0] & 0xe0) == 0xc0 &&
- (utf8[1] & 0xc0) == 0x80) {
- *ucs4 =
- ((utf8[0] & 0x1fL) << 6) |
- ((utf8[1] & 0x3fL) << 0);
- if (*ucs4 >= 0x00000080L)
- return utf8 - start + 2;
- }
- else if ((utf8[0] & 0xf0) == 0xe0 &&
- (utf8[1] & 0xc0) == 0x80 &&
- (utf8[2] & 0xc0) == 0x80) {
- *ucs4 =
- ((utf8[0] & 0x0fL) << 12) |
- ((utf8[1] & 0x3fL) << 6) |
- ((utf8[2] & 0x3fL) << 0);
- if (*ucs4 >= 0x00000800L)
- return utf8 - start + 3;
- }
- else if ((utf8[0] & 0xf8) == 0xf0 &&
- (utf8[1] & 0xc0) == 0x80 &&
- (utf8[2] & 0xc0) == 0x80 &&
- (utf8[3] & 0xc0) == 0x80) {
- *ucs4 =
- ((utf8[0] & 0x07L) << 18) |
- ((utf8[1] & 0x3fL) << 12) |
- ((utf8[2] & 0x3fL) << 6) |
- ((utf8[3] & 0x3fL) << 0);
- if (*ucs4 >= 0x00010000L)
- return utf8 - start + 4;
- }
- else if ((utf8[0] & 0xfc) == 0xf8 &&
- (utf8[1] & 0xc0) == 0x80 &&
- (utf8[2] & 0xc0) == 0x80 &&
- (utf8[3] & 0xc0) == 0x80 &&
- (utf8[4] & 0xc0) == 0x80) {
- *ucs4 =
- ((utf8[0] & 0x03L) << 24) |
- ((utf8[1] & 0x3fL) << 18) |
- ((utf8[2] & 0x3fL) << 12) |
- ((utf8[3] & 0x3fL) << 6) |
- ((utf8[4] & 0x3fL) << 0);
- if (*ucs4 >= 0x00200000L)
- return utf8 - start + 5;
- }
- else if ((utf8[0] & 0xfe) == 0xfc &&
- (utf8[1] & 0xc0) == 0x80 &&
- (utf8[2] & 0xc0) == 0x80 &&
- (utf8[3] & 0xc0) == 0x80 &&
- (utf8[4] & 0xc0) == 0x80 &&
- (utf8[5] & 0xc0) == 0x80) {
- *ucs4 =
- ((utf8[0] & 0x01L) << 30) |
- ((utf8[1] & 0x3fL) << 24) |
- ((utf8[2] & 0x3fL) << 18) |
- ((utf8[3] & 0x3fL) << 12) |
- ((utf8[4] & 0x3fL) << 6) |
- ((utf8[5] & 0x3fL) << 0);
- if (*ucs4 >= 0x04000000L)
- return utf8 - start + 6;
- }
-
- ++utf8;
- }
-}
-
-/*
- * NAME: utf8->encodechar()
- * DESCRIPTION: encode a single ucs4 char into a series of up to 6 utf8 chars
- */
-id3_length_t id3_utf8_encodechar(id3_utf8_t *utf8, id3_ucs4_t ucs4)
-{
- if (ucs4 <= 0x0000007fL) {
- utf8[0] = ucs4;
-
- return 1;
- }
- else if (ucs4 <= 0x000007ffL) {
- utf8[0] = 0xc0 | ((ucs4 >> 6) & 0x1f);
- utf8[1] = 0x80 | ((ucs4 >> 0) & 0x3f);
-
- return 2;
- }
- else if (ucs4 <= 0x0000ffffL) {
- utf8[0] = 0xe0 | ((ucs4 >> 12) & 0x0f);
- utf8[1] = 0x80 | ((ucs4 >> 6) & 0x3f);
- utf8[2] = 0x80 | ((ucs4 >> 0) & 0x3f);
-
- return 3;
- }
- else if (ucs4 <= 0x001fffffL) {
- utf8[0] = 0xf0 | ((ucs4 >> 18) & 0x07);
- utf8[1] = 0x80 | ((ucs4 >> 12) & 0x3f);
- utf8[2] = 0x80 | ((ucs4 >> 6) & 0x3f);
- utf8[3] = 0x80 | ((ucs4 >> 0) & 0x3f);
-
- return 4;
- }
- else if (ucs4 <= 0x03ffffffL) {
- utf8[0] = 0xf8 | ((ucs4 >> 24) & 0x03);
- utf8[1] = 0x80 | ((ucs4 >> 18) & 0x3f);
- utf8[2] = 0x80 | ((ucs4 >> 12) & 0x3f);
- utf8[3] = 0x80 | ((ucs4 >> 6) & 0x3f);
- utf8[4] = 0x80 | ((ucs4 >> 0) & 0x3f);
-
- return 5;
- }
- else if (ucs4 <= 0x7fffffffL) {
- utf8[0] = 0xfc | ((ucs4 >> 30) & 0x01);
- utf8[1] = 0x80 | ((ucs4 >> 24) & 0x3f);
- utf8[2] = 0x80 | ((ucs4 >> 18) & 0x3f);
- utf8[3] = 0x80 | ((ucs4 >> 12) & 0x3f);
- utf8[4] = 0x80 | ((ucs4 >> 6) & 0x3f);
- utf8[5] = 0x80 | ((ucs4 >> 0) & 0x3f);
-
- return 6;
- }
-
- /* default */
-
- return id3_utf8_encodechar(utf8, ID3_UCS4_REPLACEMENTCHAR);
-}
-
-/*
- * NAME: utf8->decode()
- * DESCRIPTION: decode a complete utf8 string into a ucs4 string
- */
-void id3_utf8_decode(id3_utf8_t const *utf8, id3_ucs4_t *ucs4)
-{
- do
- utf8 += id3_utf8_decodechar(utf8, ucs4);
- while (*ucs4++);
-}
-
-/*
- * NAME: utf8->encode()
- * DESCRIPTION: encode a complete ucs4 string into a utf8 string
- */
-void id3_utf8_encode(id3_utf8_t *utf8, id3_ucs4_t const *ucs4)
-{
- do
- utf8 += id3_utf8_encodechar(utf8, *ucs4);
- while (*ucs4++);
-}
-
-/*
- * NAME: utf8->put()
- * DESCRIPTION: serialize a single utf8 character
- */
-id3_length_t id3_utf8_put(id3_byte_t **ptr, id3_utf8_t utf8)
-{
- if (ptr)
- *(*ptr)++ = utf8;
-
- return 1;
-}
-
-/*
- * NAME: utf8->get()
- * DESCRIPTION: deserialize a single utf8 character
- */
-id3_utf8_t id3_utf8_get(id3_byte_t const **ptr)
-{
- return *(*ptr)++;
-}
-
-/*
- * NAME: utf8->serialize()
- * DESCRIPTION: serialize a ucs4 string using utf8 encoding
- */
-id3_length_t id3_utf8_serialize(id3_byte_t **ptr, id3_ucs4_t const *ucs4,
- int terminate)
-{
- id3_length_t size = 0;
- id3_utf8_t utf8[6], *out;
-
- while (*ucs4) {
- switch (id3_utf8_encodechar(out = utf8, *ucs4++)) {
- case 6: size += id3_utf8_put(ptr, *out++);
- case 5: size += id3_utf8_put(ptr, *out++);
- case 4: size += id3_utf8_put(ptr, *out++);
- case 3: size += id3_utf8_put(ptr, *out++);
- case 2: size += id3_utf8_put(ptr, *out++);
- case 1: size += id3_utf8_put(ptr, *out++);
- case 0: break;
- }
- }
-
- if (terminate)
- size += id3_utf8_put(ptr, 0);
-
- return size;
-}
-
-/*
- * NAME: utf8->deserialize()
- * DESCRIPTION: deserialize a ucs4 string using utf8 encoding
- */
-id3_ucs4_t *id3_utf8_deserialize(id3_byte_t const **ptr, id3_length_t length)
-{
- id3_byte_t const *end;
- id3_utf8_t *utf8ptr, *utf8;
- id3_ucs4_t *ucs4;
-
- end = *ptr + length;
-
- utf8 = malloc((length + 1) * sizeof(*utf8));
- if (utf8 == 0)
- return 0;
-
- utf8ptr = utf8;
- while (end - *ptr > 0 && (*utf8ptr = id3_utf8_get(ptr)))
- ++utf8ptr;
-
- *utf8ptr = 0;
-
- ucs4 = malloc((id3_utf8_length(utf8) + 1) * sizeof(*ucs4));
- if (ucs4)
- id3_utf8_decode(utf8, ucs4);
-
- free(utf8);
-
- return ucs4;
-}
diff --git a/src/libid3tag/utf8.h b/src/libid3tag/utf8.h
deleted file mode 100644
index 572bb2a..0000000
--- a/src/libid3tag/utf8.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: utf8.h,v 1.7 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_UTF8_H
-# define LIBID3TAG_UTF8_H
-
-# include "id3tag.h"
-
-id3_length_t id3_utf8_length(id3_utf8_t const *);
-id3_length_t id3_utf8_size(id3_utf8_t const *);
-
-id3_length_t id3_utf8_decodechar(id3_utf8_t const *, id3_ucs4_t *);
-id3_length_t id3_utf8_encodechar(id3_utf8_t *, id3_ucs4_t);
-
-void id3_utf8_decode(id3_utf8_t const *, id3_ucs4_t *);
-void id3_utf8_encode(id3_utf8_t *, id3_ucs4_t const *);
-
-id3_length_t id3_utf8_put(id3_byte_t **, id3_utf8_t);
-id3_utf8_t id3_utf8_get(id3_byte_t const **);
-
-id3_length_t id3_utf8_serialize(id3_byte_t **, id3_ucs4_t const *, int);
-id3_ucs4_t *id3_utf8_deserialize(id3_byte_t const **, id3_length_t);
-
-# endif
diff --git a/src/libid3tag/util.c b/src/libid3tag/util.c
deleted file mode 100644
index 61ccccf..0000000
--- a/src/libid3tag/util.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: util.c,v 1.9 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include <stdlib.h>
-# include <zlib.h>
-
-# include "id3tag.h"
-# include "util.h"
-
-/*
- * NAME: util->unsynchronise()
- * DESCRIPTION: perform (in-place) unsynchronisation
- */
-id3_length_t id3_util_unsynchronise(id3_byte_t *data, id3_length_t length)
-{
- id3_length_t bytes = 0, count;
- id3_byte_t *end = data + length;
- id3_byte_t const *ptr;
-
- if (length == 0)
- return 0;
-
- for (ptr = data; ptr < end - 1; ++ptr) {
- if (ptr[0] == 0xff && (ptr[1] == 0x00 || (ptr[1] & 0xe0) == 0xe0))
- ++bytes;
- }
-
- if (bytes) {
- ptr = end;
- end += bytes;
-
- *--end = *--ptr;
-
- for (count = bytes; count; *--end = *--ptr) {
- if (ptr[-1] == 0xff && (ptr[0] == 0x00 || (ptr[0] & 0xe0) == 0xe0)) {
- *--end = 0x00;
- --count;
- }
- }
- }
-
- return length + bytes;
-}
-
-/*
- * NAME: util->deunsynchronise()
- * DESCRIPTION: undo unsynchronisation (in-place)
- */
-id3_length_t id3_util_deunsynchronise(id3_byte_t *data, id3_length_t length)
-{
- id3_byte_t const *old, *end = data + length;
- id3_byte_t *new;
-
- if (length == 0)
- return 0;
-
- for (old = new = data; old < end - 1; ++old) {
- *new++ = *old;
- if (old[0] == 0xff && old[1] == 0x00)
- ++old;
- }
-
- *new++ = *old;
-
- return new - data;
-}
-
-/*
- * NAME: util->compress()
- * DESCRIPTION: perform zlib deflate method compression
- */
-id3_byte_t *id3_util_compress(id3_byte_t const *data, id3_length_t length,
- id3_length_t *newlength)
-{
- id3_byte_t *compressed;
-
- *newlength = length + 12;
- *newlength += *newlength / 1000;
-
- compressed = malloc(*newlength);
- if (compressed) {
- if (compress2(compressed, newlength, data, length,
- Z_BEST_COMPRESSION) != Z_OK ||
- *newlength >= length) {
- free(compressed);
- compressed = 0;
- }
- else {
- id3_byte_t *resized;
-
- resized = realloc(compressed, *newlength ? *newlength : 1);
- if (resized)
- compressed = resized;
- }
- }
-
- return compressed;
-}
-
-/*
- * NAME: util->decompress()
- * DESCRIPTION: undo zlib deflate method compression
- */
-id3_byte_t *id3_util_decompress(id3_byte_t const *data, id3_length_t length,
- id3_length_t newlength)
-{
- id3_byte_t *decompressed;
-
- decompressed = malloc(newlength ? newlength : 1);
- if (decompressed) {
- id3_length_t size;
-
- size = newlength;
-
- if (uncompress(decompressed, &size, data, length) != Z_OK ||
- size != newlength) {
- free(decompressed);
- decompressed = 0;
- }
- }
-
- return decompressed;
-}
diff --git a/src/libid3tag/util.h b/src/libid3tag/util.h
deleted file mode 100644
index 4b895d2..0000000
--- a/src/libid3tag/util.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: util.h,v 1.6 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_UTIL_H
-# define LIBID3TAG_UTIL_H
-
-# include "id3tag.h"
-
-id3_length_t id3_util_unsynchronise(id3_byte_t *, id3_length_t);
-id3_length_t id3_util_deunsynchronise(id3_byte_t *, id3_length_t);
-
-id3_byte_t *id3_util_compress(id3_byte_t const *, id3_length_t,
- id3_length_t *);
-id3_byte_t *id3_util_decompress(id3_byte_t const *, id3_length_t,
- id3_length_t);
-
-# endif
diff --git a/src/libid3tag/version.c b/src/libid3tag/version.c
deleted file mode 100644
index d54b80a..0000000
--- a/src/libid3tag/version.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: version.c,v 1.7 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
-
-# include "global.h"
-
-# include "id3tag.h"
-# include "version.h"
-
-char const id3_version[] = "ID3 Tag Library " ID3_VERSION;
-char const id3_copyright[] = "Copyright (C) " ID3_PUBLISHYEAR " " ID3_AUTHOR;
-char const id3_author[] = ID3_AUTHOR " <" ID3_EMAIL ">";
-
-char const id3_build[] = ""
-# if defined(DEBUG)
- "DEBUG "
-# elif defined(NDEBUG)
- "NDEBUG "
-# endif
-
-# if defined(EXPERIMENTAL)
- "EXPERIMENTAL "
-# endif
-;
diff --git a/src/libid3tag/version.h b/src/libid3tag/version.h
deleted file mode 100644
index 5eaa11f..0000000
--- a/src/libid3tag/version.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * libid3tag - ID3 tag manipulation library
- * Copyright (C) 2000-2004 Underbit Technologies, Inc.
- *
- * 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 program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * $Id: version.h,v 1.7 2004/01/23 09:41:32 rob Exp $
- */
-
-# ifndef LIBID3TAG_VERSION_H
-# define LIBID3TAG_VERSION_H
-
-# endif
diff --git a/src/tests/Makefile b/src/tests/Makefile
deleted file mode 100644
index d37480d..0000000
--- a/src/tests/Makefile
+++ /dev/null
@@ -1,54 +0,0 @@
-include ../../buildsys.mk
-include ../../extra.mk
-
-OBJECTIVE_LIBS_NOINST = tuple_formatter_test \
- tuple_formatter_functor_test \
- tag_wma_test
-
-LDFLAGS += $(AUDLDFLAGS)
-LDADD = \
- $(DBUS_LIBS) \
- $(GTK_LIBS) \
- $(MOWGLI_LIBS)
-
-CFLAGS += \
- $(GTK_CFLAGS) \
- $(DBUS_CFLAGS) \
- $(AUDACIOUS_DEFINES) \
- $(ARCH_DEFINES) \
- $(MOWGLI_CFLAGS) \
- -I.. -I../.. \
- -I../intl -I../audacious
-
-
-AUDCORE_OBJS = ../libaudcore/tuple.o ../libaudcore/tuple_formatter.o \
- ../libaudcore/audstrings.o ../libaudcore/tuple_compiler.o
-
-AUDTAG_OBJS = ../libaudtag/util.o ../libaudtag/wma/guid.o \
- ../libaudtag/wma/wma.o ../libaudtag/wma/wma_fmt.o
-
-COMMON_OBJS = test_harness.o $(AUDCORE_OBJS)
-
-TFT_OBJS = $(COMMON_OBJS) tuple_formatter_test.o
-
-tuple_formatter_test: $(TFT_OBJS)
- $(CC) $(LDFLAGS) $(TFT_OBJS) $(LDADD) -o $@
- @printf "%10s %-20s\n" LINK $@
- ./$@
- @printf "%10s %-20s\n" TEST-PASS $@
-
-TFFT_OBJS = $(COMMON_OBJS) tuple_formatter_functor_test.o
-tuple_formatter_functor_test: $(TFFT_OBJS)
- $(CC) $(LDFLAGS) $(TFFT_OBJS) $(LDADD) -o $@
- @printf "%10s %-20s\n" LINK $@
- ./$@
- @printf "%10s %-20s\n" TEST-PASS $@
-
-TAG_WMA_OBJS = $(COMMON_OBJS) $(AUDTAG_OBJS) tag_wma_test.o
-tag_wma_test: $(TAG_WMA_OBJS)
- $(CC) $(LDFLAGS) $(TAG_WMA_OBJS) $(LDADD) -o $@ -laudcore
- @printf "%10s %-20s\n" LINK $@
- ./$@
- @printf "%10s %-20s\n" TEST-PASS $@
-
-
diff --git a/src/tests/README b/src/tests/README
deleted file mode 100644
index 67adc5d..0000000
--- a/src/tests/README
+++ /dev/null
@@ -1,11 +0,0 @@
-This directory contains some tests. To run them, type "make".
-
-Any needed uncompiled files in the audacious core will be compiled
-with the proper CFLAGS. Don't worry about that.
-
-You can help make this directory more useful by writing tests as
-you fix bugs. Unless they're in the UI, autotesting that may be
-problematic.
-
-To write a test, simply edit an existing test and the Makefile
-as required.
diff --git a/src/tests/tag_wma_test.c b/src/tests/tag_wma_test.c
deleted file mode 100644
index 6690e0d..0000000
--- a/src/tests/tag_wma_test.c
+++ /dev/null
@@ -1,98 +0,0 @@
-#include <glib.h>
-#include <libaudcore/tuple.h>
-#define TEST
-#include <libaudtag/util.h>
-#include <libaudtag/wma/wma.h>
-
-#define WMA1_FILE "test_wma1.wma"
-#define WMA1_FILE_OUT "test_wma1_out.wma"
-#define WMA2_FILE "test_wma2.wma"
-
-int test_read(int n, char* f) {
-
- Tuple * test_tuple;
- test_tuple = tuple_new();
-
- tuple_associate_string(test_tuple, FIELD_FILE_PATH, NULL, f);
-
- test_tuple = wma_populate_tuple_from_file(test_tuple);
-
- const char *file_path = tuple_get_string(test_tuple, FIELD_FILE_PATH, NULL);
-
- if (g_ascii_strcasecmp(file_path, f)) {
- g_print("tagging failure on test %d:\n"
- "'%s' != '%s' \n",
- n, file_path, f);
- tuple_free(test_tuple);
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
-}
-
-int test_write(int n, char *f) {
-
- char *title = "Title 제목 ",
- *author = "Author المؤلف",
- *comment = "Comment Коментар",
- *album = "Album 相冊",
- *genre = "Genre शैली";
- Tuple * test_tuple = tuple_new();
- test_tuple = wma_populate_tuple_from_file(test_tuple);
-
- Tuple *write_test_tuple = makeTuple(test_tuple,
- title, author,
- comment, album,
- genre, "2111",
- f, 2);
-
- wma_write_tuple_to_file(write_test_tuple);
- wma_populate_tuple_from_file(test_tuple);
-
- const char* title_new = tuple_get_string(test_tuple, FIELD_TITLE, NULL);
- const char* author_new = tuple_get_string(test_tuple, FIELD_ARTIST, NULL);
- const char* comment_new = tuple_get_string(test_tuple, FIELD_COMMENT, NULL);
- const char* album_new = tuple_get_string(test_tuple, FIELD_ALBUM, NULL);
- const char* genre_new = tuple_get_string(test_tuple, FIELD_GENRE, NULL);
-
- if (g_ascii_strcasecmp(title, title_new) ||
- g_ascii_strcasecmp(author, author_new) ||
- g_ascii_strcasecmp(comment, comment_new) ||
- g_ascii_strcasecmp(album, album_new) ||
- g_ascii_strcasecmp(genre, genre_new)) {
- g_print("tagging failure on test %d:\n"
- "'%s' != '%s' \n"
- "'%s' != '%s' \n"
- "'%s' != '%s' \n"
- "'%s' != '%s' \n"
- "'%s' != '%s' \n",
- n,
- title, title_new,
- author, author_new,
- comment, comment_new,
- album, album_new,
- genre, genre_new);
-
- tuple_free(test_tuple);
- tuple_free(write_test_tuple);
- return EXIT_FAILURE;
- }
- return EXIT_SUCCESS;
-}
-
-int test_run(int argc, char *argv[]) {
-
- if (test_read(1, WMA1_FILE) == EXIT_FAILURE)
- return EXIT_FAILURE;
-
- if (test_read(2, WMA2_FILE) == EXIT_FAILURE)
- return EXIT_FAILURE;
-
-
- if (test_write(3, WMA1_FILE) == EXIT_FAILURE)
- return EXIT_FAILURE;
-
- if (test_write(4, WMA2_FILE) == EXIT_FAILURE)
- return EXIT_FAILURE;
-
- return EXIT_SUCCESS;
-}
diff --git a/src/tests/test_harness.c b/src/tests/test_harness.c
deleted file mode 100644
index 37fe7cf..0000000
--- a/src/tests/test_harness.c
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Audacious
- * Copyright (c) 2007 William Pitcock
- *
- * 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; under version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses>.
- *
- * The Audacious team does not consider modular code linking to
- * Audacious or using our public API to be a derived work.
- */
-
-#include <glib.h>
-#include <mowgli.h>
-
-extern int test_run(gint argc, const gchar *argv[]);
-
-int
-main(gint argc, const gchar *argv[])
-{
- g_thread_init(NULL);
-
- mowgli_init();
-
- if (!g_thread_supported())
- mowgli_log("Warning: GThread not supported. Some tests may fail.");
-
- return test_run(argc, argv);
-}
-
diff --git a/src/tests/test_wma1.wma b/src/tests/test_wma1.wma
deleted file mode 100644
index 4a33136..0000000
--- a/src/tests/test_wma1.wma
+++ /dev/null
Binary files differ
diff --git a/src/tests/test_wma2.wma b/src/tests/test_wma2.wma
deleted file mode 100644
index ece725d..0000000
--- a/src/tests/test_wma2.wma
+++ /dev/null
Binary files differ
diff --git a/src/tests/tuple_formatter_functor_test.c b/src/tests/tuple_formatter_functor_test.c
deleted file mode 100644
index 3a8d7fb..0000000
--- a/src/tests/tuple_formatter_functor_test.c
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Audacious
- * Copyright (c) 2007 William Pitcock
- *
- * 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; under version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses>.
- *
- * The Audacious team does not consider modular code linking to
- * Audacious or using our public API to be a derived work.
- */
-
-#include <glib.h>
-#include <mowgli.h>
-
-#include <libaudcore/tuple.h>
-#include <libaudcore/tuple_formatter.h>
-
-static gboolean
-test_functor(Tuple *tuple, const char *expr)
-{
- return TRUE;
-}
-
-int
-test_run(int argc, const char *argv[])
-{
- Tuple *tuple;
- gchar *tstr;
-
- tuple_formatter_register_expression("(true)", test_functor);
-
- tuple = tuple_new();
- tuple_associate_string(tuple, FIELD_ARTIST, "splork", "moo");
-
- tstr = tuple_formatter_process_string(tuple, "${(true):${splork}}");
- if (g_ascii_strcasecmp(tstr, "moo"))
- {
- g_print("fail 1: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "%{audacious-version}");
- if (g_str_has_prefix(tstr, "audacious") == FALSE)
- {
- g_print("fail 2: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${(true):%{audacious-version}}");
- if (g_str_has_prefix(tstr, "audacious") == FALSE)
- {
- g_print("fail 3: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- mowgli_object_unref(tuple);
-
- return EXIT_SUCCESS;
-}
diff --git a/src/tests/tuple_formatter_test.c b/src/tests/tuple_formatter_test.c
deleted file mode 100644
index febdf50..0000000
--- a/src/tests/tuple_formatter_test.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Audacious
- * Copyright (c) 2007 William Pitcock
- *
- * 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; under version 3 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses>.
- *
- * The Audacious team does not consider modular code linking to
- * Audacious or using our public API to be a derived work.
- */
-
-#include <glib.h>
-#include <mowgli.h>
-
-#include <libaudcore/tuple.h>
-#include <libaudcore/tuple_formatter.h>
-
-int
-test_run(int argc, const char *argv[])
-{
- Tuple *tuple;
- gchar *tstr;
-
- tuple = tuple_new();
- tuple_associate_string(tuple, FIELD_ARTIST, "splork", "moo");
- tuple_associate_int(tuple, FIELD_TRACK_NUMBER, "splorkerz", 42);
-
- tstr = tuple_formatter_process_string(tuple, "${splork} ${splorkerz}");
- if (g_ascii_strcasecmp(tstr, "moo 42"))
- {
- g_print("fail 1: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${?fizz:${splork}} ${splorkerz}");
- if (g_ascii_strcasecmp(tstr, " 42"))
- {
- g_print("fail 2: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${?splork:${splork}} ${splorkerz}");
- if (g_ascii_strcasecmp(tstr, "moo 42"))
- {
- g_print("fail 3: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${==splork,splork:fields given matched}");
- if (g_ascii_strcasecmp(tstr, "fields given matched"))
- {
- g_print("fail 4: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${==splork,splork:${splork}}");
- if (g_ascii_strcasecmp(tstr, "moo"))
- {
- g_print("fail 5: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${!=splork,splorkerz:fields did not match}");
- if (g_ascii_strcasecmp(tstr, "fields did not match"))
- {
- g_print("fail 6: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${!=splork,splorkerz:${splorkerz}}");
- if (g_ascii_strcasecmp(tstr, "42"))
- {
- g_print("fail 7: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${!=splork,splork:${splorkerz}}");
- if (g_ascii_strcasecmp(tstr, ""))
- {
- g_print("fail 8: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${(empty)?splorky:${splorkerz}}");
- if (g_ascii_strcasecmp(tstr, "42"))
- {
- g_print("fail 9: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${?splork:${splork} - }${splork}");
- if (g_ascii_strcasecmp(tstr, "moo - moo"))
- {
- g_print("fail 10: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${?splork:${?splork:${splork}} - }${splork}");
- if (g_ascii_strcasecmp(tstr, "moo - moo"))
- {
- g_print("fail 11: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${?splork:${splork} - }${?splork:${splork} - }${splork}");
- if (g_ascii_strcasecmp(tstr, "moo - moo - moo"))
- {
- g_print("fail 12: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tuple_associate_string(tuple, FIELD_ARTIST, "sheep", "");
-
- tstr = tuple_formatter_process_string(tuple, "${?splork:${splork} - }${?sheep:${sheep} - }${splork}");
- if (g_ascii_strcasecmp(tstr, "moo - - moo"))
- {
- g_print("fail 13: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${?splork:${splork} - }${?sheep:${sheep} - }${splork}");
- if (g_ascii_strcasecmp(tstr, "moo - - moo"))
- {
- g_print("fail 14: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${==splork,\"moo\":const text field matches}");
- if (g_ascii_strcasecmp(tstr, "const text field matches"))
- {
- g_print("fail 15: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${==\"moo\",\"moo\":const text fields match}");
- if (g_ascii_strcasecmp(tstr, "const text fields match"))
- {
- g_print("fail 16: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${!=splork,\"muu\":const text field doesn't match}");
- if (g_ascii_strcasecmp(tstr, "const text field doesn't match"))
- {
- g_print("fail 17: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- tstr = tuple_formatter_process_string(tuple, "${!=\"moo\",\"muu\":const text fields do not match}");
- if (g_ascii_strcasecmp(tstr, "const text fields do not match"))
- {
- g_print("fail 18: '%s'\n", tstr);
- return EXIT_FAILURE;
- }
- g_free(tstr);
-
- mowgli_object_unref(tuple);
-
- return EXIT_SUCCESS;
-}