# HG changeset patch # User mf0102 # Date 1169928621 28800 # Node ID 3ec22a11c83e574802ce6eba206184a9142c5b71 # Parent 4e2fc64d95efb5433a55a7db374c0442ce5977a7 [svn] - moved titlestring.* and xconvert.* from libaudacious to audacious diff -r 4e2fc64d95ef -r 3ec22a11c83e ChangeLog --- a/ChangeLog Sat Jan 27 11:40:05 2007 -0800 +++ b/ChangeLog Sat Jan 27 12:10:21 2007 -0800 @@ -1,3 +1,14 @@ +2007-01-27 19:40:05 +0000 William Pitcock + revision [3870] + - make vfs_buffered_file_new_from_uri declaration const + - cope properly with subsong URIs + + trunk/src/audacious/input.c | 14 ++++++++++++-- + trunk/src/audacious/vfs_buffered_file.c | 2 +- + trunk/src/audacious/vfs_buffered_file.h | 2 +- + 3 files changed, 14 insertions(+), 4 deletions(-) + + 2007-01-27 19:28:14 +0000 William Pitcock revision [3868] - fix an offset error in the vfs_buffered_file wraparound implementation sections diff -r 4e2fc64d95ef -r 3ec22a11c83e src/audacious/Makefile --- a/src/audacious/Makefile Sat Jan 27 11:40:05 2007 -0800 +++ b/src/audacious/Makefile Sat Jan 27 12:10:21 2007 -0800 @@ -42,8 +42,10 @@ ui_preferences.h \ util.h \ strings.h \ + titlestring.h \ vfs.h \ - vfs_buffer.h + vfs_buffer.h \ + xconvert.h SOURCES = \ build_stamp.c \ @@ -74,6 +76,7 @@ pluginenum.c \ signals.c \ strings.c \ + titlestring.c \ ui_about.c \ ui_credits.c \ ui_equalizer.c \ @@ -92,7 +95,8 @@ vfs_buffered_file.c \ vfs.c \ vfs_common.c \ - visualization.c + visualization.c \ + xconvert.c OBJECTS = ${SOURCES:.c=.o} diff -r 4e2fc64d95ef -r 3ec22a11c83e src/audacious/titlestring.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/audacious/titlestring.c Sat Jan 27 12:10:21 2007 -0800 @@ -0,0 +1,449 @@ +/* + * Copyright (C) 2001, Espen Skoglund + * Copyright (C) 2001, Haavard Kvaalen + * + * 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. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#define GETTEXT_PACKAGE PACKAGE_NAME + +#include +#include +#include +#include +#include + +#include "titlestring.h" + +#define CHECK(input, field) \ + (((gchar *) &input->field - (gchar *) input) < input->__size) + +#define VS(input, field) (CHECK(input, field) ? input->field : NULL) +#define VI(input, field) (CHECK(input, field) ? input->field : 0) + +/** + * bmp_title_input_new: + * + * #BmpTitleInput tuple factory. + * + * Return value: A #BmpTitleInput object. + **/ +BmpTitleInput * +bmp_title_input_new() +{ + BmpTitleInput *input; + input = g_new0(BmpTitleInput, 1); + input->__size = XMMS_TITLEINPUT_SIZE; + input->__version = XMMS_TITLEINPUT_VERSION; + return input; +} + +/** + * bmp_title_input_free: + * @input: A #BmpTitleInput tuple to destroy. + * + * Destroys a #BmpTitleInput tuple. + **/ +void +bmp_title_input_free(BmpTitleInput * input) +{ + if (input == NULL) + return; + + if (input->performer != NULL) + g_free(input->performer); + + if (input->album_name != NULL) + g_free(input->album_name); + + if (input->track_name != NULL) + g_free(input->track_name); + + if (input->date != NULL) + g_free(input->date); + + if (input->genre != NULL) + g_free(input->genre); + + if (input->comment != NULL) + g_free(input->comment); + + if (input->file_name != NULL) + g_free(input->file_name); + + if (input->file_path != NULL) + g_free(input->file_path); + + g_free(input); +} + +/** + * xmms_get_titlestring: + * @fmt: A format string. + * @input: A tuple to use for data. + * + * Generates a formatted string from a tuple. + * + * Return value: A formatted tuple string. + **/ +gchar * +xmms_get_titlestring(const gchar * fmt, TitleInput * input) +{ + GString *outstr; + const gchar *string; + gchar c, convert[16]; + gint numdigits, numpr, val, i; + gint f_left, f_space, f_zero, someflag, width, precision; + gboolean did_output = FALSE; + gchar digits[] = "0123456789"; + +#define PUTCH(ch) g_string_append_c(outstr, ch) + +#define LEFTPAD(num) \ + G_STMT_START { \ + gint cnt = (num); \ + if ( ! f_left && cnt > 0 ) \ + while ( cnt-- > 0 ) \ + PUTCH(f_zero ? '0' : ' '); \ + } G_STMT_END; + +#define RIGHTPAD(num) \ + G_STMT_START { \ + gint cnt = (num); \ + if ( f_left && cnt > 0 ) \ + while ( cnt-- > 0 ) \ + PUTCH( ' ' ); \ + } G_STMT_END; + + if (fmt == NULL || input == NULL) + return NULL; + outstr = g_string_new(""); + + for (;;) { + /* Copy characters until we encounter '%'. */ + while ((c = *fmt++) != '%') { + if (c == '\0') + goto Done; + g_string_append_c(outstr, c); + } + + f_left = f_space = f_zero = 0; + someflag = 1; + + + /* Parse flags. */ + while (someflag) { + switch (*fmt) { + case '-': + f_left = 1; + fmt++; + break; + case ' ': + f_space = 1; + fmt++; + break; + case '0': + f_zero = 1; + fmt++; + break; + default: + someflag = 0; + break; + } + } + + + /* Parse field width. */ + if ((c = *fmt) >= '0' && c <= '9') { + width = 0; + while ((c = *fmt++) >= '0' && c <= '9') { + width *= 10; + width += c - '0'; + } + fmt--; + } + else + width = -1; + + + /* Parse precision. */ + if (*fmt == '.') { + if ((c = *++fmt) >= '0' && c <= '9') { + precision = 0; + while ((c = *fmt++) >= '0' && c <= '9') { + precision *= 10; + precision += c - '0'; + } + fmt--; + } + else + precision = -1; + } + else + precision = -1; + + + /* Parse format conversion. */ + switch (c = *fmt++) { + case '}': /* close optional, just ignore */ + continue; + + case '{':{ /* optional entry: %{n:...%} */ + char n = *fmt++; + if (!((n == 'a' && VS(input, album_name)) || + (n == 'c' && VS(input, comment)) || + (n == 'd' && VS(input, date)) || + (n == 'e' && VS(input, file_ext)) || + (n == 'f' && VS(input, file_name)) || + (n == 'F' && VS(input, file_path)) || + (n == 'g' && VS(input, genre)) || + (n == 'n' && VI(input, track_number)) || + (n == 'p' && VS(input, performer)) || + (n == 't' && VS(input, track_name)) || + (n == 'y' && VI(input, year)))) { + int nl = 0; + char c; + while ((c = *fmt++)) /* until end of string */ + if (c == '}') /* if end of opt */ + if (!nl) + break; /* if outmost indent level */ + else + --nl; /* else reduce indent */ + else if (c == '{') + ++nl; /* increase indent */ + } + else + ++fmt; + break; + } + + case 'a': + string = VS(input, album_name); + goto Print_string; + case 'c': + string = VS(input, comment); + goto Print_string; + case 'd': + string = VS(input, date); + goto Print_string; + case 'e': + string = VS(input, file_ext); + goto Print_string; + case 'f': + string = VS(input, file_name); + goto Print_string; + case 'F': + string = VS(input, file_path); + goto Print_string; + case 'g': + string = VS(input, genre); + goto Print_string; + case 'n': + val = VI(input, track_number); + goto Print_number; + case 'p': + string = VS(input, performer); + goto Print_string; + case 't': + string = VS(input, track_name); + goto Print_string; + case 'y': + val = VI(input, year); + goto Print_number; + + Print_string: + if (string == NULL) + break; + did_output = TRUE; + + numpr = 0; + if (width > 0) { + /* Calculate printed size. */ + numpr = strlen(string); + if (precision >= 0 && precision < numpr) + numpr = precision; + + LEFTPAD(width - numpr); + } + + /* Insert string. */ + if (precision >= 0) { + glong offset_max = precision, offset; + gchar *uptr = NULL; + const gchar *tmpstring = string; + while (precision > 0) { + offset = offset_max - precision; + uptr = g_utf8_offset_to_pointer(tmpstring, offset); + if (*uptr == '\0') + break; + g_string_append_unichar(outstr, g_utf8_get_char(uptr)); + precision--; + } + } + else { + while ((c = *string++) != '\0') + PUTCH(c); + } + + RIGHTPAD(width - numpr); + break; + + Print_number: + if (val == 0) + break; + if (c != 'N') + did_output = TRUE; + + /* Create reversed number string. */ + numdigits = 0; + do { + convert[numdigits++] = digits[val % 10]; + val /= 10; + } + while (val > 0); + + numpr = numdigits > precision ? numdigits : precision; + + /* Insert left padding. */ + if (!f_left && width > numpr) { + if (f_zero) + numpr = width; + else + for (i = width - numpr; i-- > 0;) + PUTCH(' '); + } + + /* Insert zero padding. */ + for (i = numpr - numdigits; i-- > 0;) + PUTCH('0'); + + /* Insert number. */ + while (numdigits > 0) + PUTCH(convert[--numdigits]); + + RIGHTPAD(width - numpr); + break; + + case '%': + PUTCH('%'); + break; + + default: + PUTCH('%'); + PUTCH(c); + break; + } + } + + Done: + if (did_output) + return g_string_free(outstr, FALSE); + else + return NULL; +} + +struct _TagDescription { + gchar tag; + gchar *description; +}; + +typedef struct _TagDescription TagDescription; + +static TagDescription tag_descriptions[] = { + {'p', N_("Performer/Artist")}, + {'a', N_("Album")}, + {'g', N_("Genre")}, + {'f', N_("File name")}, + {'F', N_("File path")}, + {'e', N_("File extension")}, + {'t', N_("Track name")}, + {'n', N_("Track number")}, + {'d', N_("Date")}, + {'y', N_("Year")}, + {'c', N_("Comment")} +}; + +gint tag_descriptions_length = + sizeof(tag_descriptions) / sizeof(TagDescription); + +/** + * xmms_titlestring_descriptions: + * @tags: A list of formatters to provide. + * @columns: A number of columns to arrange them in. + * + * Generates a box explaining how to use the formatters. + * + * Return value: A GtkWidget containing the table. + **/ +GtkWidget * +xmms_titlestring_descriptions(gchar * tags, gint columns) +{ + GtkWidget *table, *label; + gchar tag_str[5]; + gint num = strlen(tags); + gint r = 0, c, i; + + g_return_val_if_fail(tags != NULL, NULL); + g_return_val_if_fail(columns <= num, NULL); + + table = gtk_table_new((num + columns - 1) / columns, columns * 2, FALSE); + gtk_table_set_row_spacings(GTK_TABLE(table), 2); + gtk_table_set_col_spacings(GTK_TABLE(table), 5); + + for (c = 0; c < columns; c++) { + for (r = 0; r < (num + columns - 1 - c) / columns; r++) { + g_snprintf(tag_str, sizeof(tag_str), "%%%c:", *tags); + label = gtk_label_new(tag_str); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 2 * c, 2 * c + 1, r, + r + 1, GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show(label); + + for (i = 0; i < tag_descriptions_length; i++) { + if (*tags == tag_descriptions[i].tag) { + label = gtk_label_new(_(tag_descriptions[i].description)); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 2 * c + 1, + 2 * c + 2, r, r + 1, + GTK_EXPAND | GTK_FILL, + GTK_EXPAND | GTK_FILL, 0, 0); + gtk_widget_show(label); + break; + } + } + + if (i == tag_descriptions_length) + g_warning("Invalid tag: %c", *tags); + + tags++; + } + + } + + label = gtk_label_new(_("%{n:...%}: Display \"...\" only if element " + "%n is present")); + gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); + gtk_table_attach(GTK_TABLE(table), label, 0, r + 1, + r + 1, r + 2, GTK_FILL, GTK_FILL, 0, 0); + gtk_widget_show(label); + + return table; +} diff -r 4e2fc64d95ef -r 3ec22a11c83e src/audacious/titlestring.h --- a/src/audacious/titlestring.h Sat Jan 27 11:40:05 2007 -0800 +++ b/src/audacious/titlestring.h Sat Jan 27 12:10:21 2007 -0800 @@ -25,13 +25,30 @@ #include #include -/* - * Struct which is passed to xmms_get_titlestring(). An input struct - * is allocated and initialized with XMMS_NEW_TITLEINPUT(). Before +/** + * TitleInput: + * @__size: Private field which describes the version of the TitleInput. + * @__version: Private field which describes the version of the TitleInput. + * @performer: The performer of the media that the tuple is describing. + * @album_name: The name of the album that contains the media. + * @track_name: The title of the media. + * @track_number: The track number of the media. + * @year: The year the media was published. + * @date: The date the media was published. + * @genre: The genre of the media. + * @comment: Any comments attached to the media. + * @file_name: The filename which refers to the media. + * @file_ext: The file's extension. + * @file_path: The path that the media is in. + * @length: The length of the media. + * @formatter: The format string that should be used. + * @mtime: The last modified time of the file. + * + * Tuple which is passed to xmms_get_titlestring(). An input tuple + * is allocated and initialized with bmp_title_input_new(). Before * passing the struct to xmms_get_titlestring() it should be filled * with appropriate field values. - */ - + **/ typedef struct { gint __size; /* Set by bmp_title_input_new() */ gint __version; /* Ditto */ @@ -47,11 +64,16 @@ gchar *file_name; /* %f */ const gchar *file_ext; /* %e *//* is not always strdup'ed, see xmms_input_get_song_info and plugins! */ gchar *file_path; /* %F */ - gint length; /* not displayable */ - gchar *formatter; /* not displayable */ - time_t mtime; /* time of modified */ + gint length; /* not displayable */ + gchar *formatter; /* not displayable */ + time_t mtime; } TitleInput; +/** + * BmpTitleInput: + * + * An alternate name for the #TitleInput object. + **/ typedef TitleInput BmpTitleInput; @@ -62,14 +84,27 @@ * the struct layout. */ +/** + * XMMS_TITLEINPUT_SIZE: + * + * The size of the TitleInput object compiled into the library. + **/ #define XMMS_TITLEINPUT_SIZE sizeof(TitleInput) + +/** + * XMMS_TITLEINPUT_VERSION: + * + * The version of the TitleInput object compiled into the library. + **/ #define XMMS_TITLEINPUT_VERSION (1) -#define XMMS_NEW_TITLEINPUT(input) G_STMT_START { \ - input = g_new0(TitleInput, 1); \ - input->__size = XMMS_TITLEINPUT_SIZE; \ - input->__version = XMMS_TITLEINPUT_VERSION; \ -} G_STMT_END +/** + * XMMS_NEW_TITLEINPUT: + * @input: A TitleInput to initialize. + * + * Initializes a TitleInput object. Included for XMMS compatibility. + **/ +#define XMMS_NEW_TITLEINPUT(input) input = bmp_title_input_new(); G_BEGIN_DECLS @@ -78,7 +113,7 @@ void bmp_title_input_free(BmpTitleInput * input); gchar *xmms_get_titlestring(const gchar * fmt, TitleInput * input); -GtkWidget *xmms_titlestring_descriptions(gchar * tags, gint rows); +GtkWidget *xmms_titlestring_descriptions(gchar * tags, gint columns); G_END_DECLS diff -r 4e2fc64d95ef -r 3ec22a11c83e src/audacious/xconvert.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/audacious/xconvert.c Sat Jan 27 12:10:21 2007 -0800 @@ -0,0 +1,849 @@ +/* Audacious + * Copyright (C) 2005-2007 Audacious team + * + * XMMS - Cross-platform multimedia player + * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, + * Thomas Nilsson and 4Front Technologies + * Copyright (C) 1999-2003 Haavard Kvaalen + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "config.h" +#include +#include +#include "xconvert.h" + +#define IS_BIG_ENDIAN (G_BYTE_ORDER==G_BIG_ENDIAN) + +/** + * buffer: + * + * Contains data for conversion. + * + * @buffer: A pointer to the memory being used in the conversion process. + * @size: The size of the memory being referenced. + **/ +struct buffer { + void *buffer; + int size; +}; + +/** + * xmms_convert_buffers: + * + * Stores data for conversion. + * + * @format_buffer: A buffer for converting formats. + * @stereo_buffer: A buffer for downmixing or upmixing. + * @freq_buffer: A buffer used for resampling. + **/ +struct xmms_convert_buffers { + struct buffer format_buffer, stereo_buffer, freq_buffer; +}; + +/** + * xmms_convert_buffers_new: + * + * Factory for an #xmms_convert_buffers struct. + * + * Return value: An #xmms_convert_buffers struct. + **/ +struct xmms_convert_buffers * +xmms_convert_buffers_new(void) +{ + return g_malloc0(sizeof(struct xmms_convert_buffers)); +} + +/** + * convert_get_buffer: + * @buffer: A buffer to resize. + * @size: The new size for that buffer. + * + * Resizes a conversion buffer. + **/ +static void * +convert_get_buffer(struct buffer *buffer, size_t size) +{ + if (size > 0 && size <= (size_t)buffer->size) + return buffer->buffer; + + buffer->size = size; + buffer->buffer = g_realloc(buffer->buffer, size); + return buffer->buffer; +} + +/** + * xmms_convert_buffers_free: + * @buf: An xmms_convert_buffers structure to free. + * + * Frees the actual buffers contained inside the buffer struct. + **/ +void +xmms_convert_buffers_free(struct xmms_convert_buffers *buf) +{ + convert_get_buffer(&buf->format_buffer, 0); + convert_get_buffer(&buf->stereo_buffer, 0); + convert_get_buffer(&buf->freq_buffer, 0); +} + +/** + * xmms_convert_buffers_destroy: + * @buf: An xmms_convert_buffers structure to destroy. + * + * Destroys an xmms_convert_buffers structure. + **/ +void +xmms_convert_buffers_destroy(struct xmms_convert_buffers *buf) +{ + if (!buf) + return; + xmms_convert_buffers_free(buf); + g_free(buf); +} + +static int +convert_swap_endian(struct xmms_convert_buffers *buf, void **data, int length) +{ + guint16 *ptr = *data; + int i; + for (i = 0; i < length; i += 2, ptr++) + *ptr = GUINT16_SWAP_LE_BE(*ptr); + + return i; +} + +static int +convert_swap_sign_and_endian_to_native(struct + xmms_convert_buffers + *buf, void **data, int length) +{ + guint16 *ptr = *data; + int i; + for (i = 0; i < length; i += 2, ptr++) + *ptr = GUINT16_SWAP_LE_BE(*ptr) ^ 1 << 15; + + return i; +} + +static int +convert_swap_sign_and_endian_to_alien(struct + xmms_convert_buffers *buf, + void **data, int length) +{ + guint16 *ptr = *data; + int i; + for (i = 0; i < length; i += 2, ptr++) + *ptr = GUINT16_SWAP_LE_BE(*ptr ^ 1 << 15); + + return i; +} + +static int +convert_swap_sign16(struct xmms_convert_buffers *buf, void **data, int length) +{ + gint16 *ptr = *data; + int i; + for (i = 0; i < length; i += 2, ptr++) + *ptr ^= 1 << 15; + + return i; +} + +static int +convert_swap_sign8(struct xmms_convert_buffers *buf, void **data, int length) +{ + gint8 *ptr = *data; + int i; + for (i = 0; i < length; i++) + *ptr++ ^= 1 << 7; + + return i; +} + +static int +convert_to_8_native_endian(struct xmms_convert_buffers *buf, + void **data, int length) +{ + gint8 *output = *data; + gint16 *input = *data; + int i; + for (i = 0; i < length / 2; i++) + *output++ = *input++ >> 8; + + return i; +} + +static int +convert_to_8_native_endian_swap_sign(struct xmms_convert_buffers + *buf, void **data, int length) +{ + gint8 *output = *data; + gint16 *input = *data; + int i; + for (i = 0; i < length / 2; i++) + *output++ = (*input++ >> 8) ^ (1 << 7); + + return i; +} + + +static int +convert_to_8_alien_endian(struct xmms_convert_buffers *buf, + void **data, int length) +{ + gint8 *output = *data; + gint16 *input = *data; + int i; + for (i = 0; i < length / 2; i++) + *output++ = *input++ & 0xff; + + return i; +} + +static int +convert_to_8_alien_endian_swap_sign(struct xmms_convert_buffers + *buf, void **data, int length) +{ + gint8 *output = *data; + gint16 *input = *data; + int i; + for (i = 0; i < length / 2; i++) + *output++ = (*input++ & 0xff) ^ (1 << 7); + + return i; +} + +static int +convert_to_16_native_endian(struct xmms_convert_buffers *buf, + void **data, int length) +{ + guint8 *input = *data; + guint16 *output; + int i; + *data = convert_get_buffer(&buf->format_buffer, length * 2); + output = *data; + for (i = 0; i < length; i++) + *output++ = *input++ << 8; + + return i * 2; +} + +static int +convert_to_16_native_endian_swap_sign(struct + xmms_convert_buffers *buf, + void **data, int length) +{ + guint8 *input = *data; + guint16 *output; + int i; + *data = convert_get_buffer(&buf->format_buffer, length * 2); + output = *data; + for (i = 0; i < length; i++) + *output++ = (*input++ << 8) ^ (1 << 15); + + return i * 2; +} + + +static int +convert_to_16_alien_endian(struct xmms_convert_buffers *buf, + void **data, int length) +{ + guint8 *input = *data; + guint16 *output; + int i; + *data = convert_get_buffer(&buf->format_buffer, length * 2); + output = *data; + for (i = 0; i < length; i++) + *output++ = *input++; + + return i * 2; +} + +static int +convert_to_16_alien_endian_swap_sign(struct xmms_convert_buffers + *buf, void **data, int length) +{ + guint8 *input = *data; + guint16 *output; + int i; + *data = convert_get_buffer(&buf->format_buffer, length * 2); + output = *data; + for (i = 0; i < length; i++) + *output++ = *input++ ^ (1 << 7); + + return i * 2; +} + +static AFormat +unnativize(AFormat fmt) +{ + if (fmt == FMT_S16_NE) { + if (IS_BIG_ENDIAN) + return FMT_S16_BE; + else + return FMT_S16_LE; + } + if (fmt == FMT_U16_NE) { + if (IS_BIG_ENDIAN) + return FMT_U16_BE; + else + return FMT_U16_LE; + } + return fmt; +} + +/** + * xmms_convert_get_func: + * @output: A format to output data as. + * @input: The format of the inbound data. + * + * Looks up the proper conversion method to use. + * + * Return value: A function pointer to the desired conversion function. + **/ +convert_func_t +xmms_convert_get_func(AFormat output, AFormat input) +{ + output = unnativize(output); + input = unnativize(input); + + if (output == input) + return NULL; + + if ((output == FMT_U16_BE && input == FMT_U16_LE) || + (output == FMT_U16_LE && input == FMT_U16_BE) || + (output == FMT_S16_BE && input == FMT_S16_LE) || + (output == FMT_S16_LE && input == FMT_S16_BE)) + return convert_swap_endian; + + if ((output == FMT_U16_BE && input == FMT_S16_BE) || + (output == FMT_U16_LE && input == FMT_S16_LE) || + (output == FMT_S16_BE && input == FMT_U16_BE) || + (output == FMT_S16_LE && input == FMT_U16_LE)) + return convert_swap_sign16; + + if ((IS_BIG_ENDIAN && + ((output == FMT_U16_BE && input == FMT_S16_LE) || + (output == FMT_S16_BE && input == FMT_U16_LE))) || + (!IS_BIG_ENDIAN && + ((output == FMT_U16_LE && input == FMT_S16_BE) || + (output == FMT_S16_LE && input == FMT_U16_BE)))) + return convert_swap_sign_and_endian_to_native; + + if ((!IS_BIG_ENDIAN && + ((output == FMT_U16_BE && input == FMT_S16_LE) || + (output == FMT_S16_BE && input == FMT_U16_LE))) || + (IS_BIG_ENDIAN && + ((output == FMT_U16_LE && input == FMT_S16_BE) || + (output == FMT_S16_LE && input == FMT_U16_BE)))) + return convert_swap_sign_and_endian_to_alien; + + if ((IS_BIG_ENDIAN && + ((output == FMT_U8 && input == FMT_U16_BE) || + (output == FMT_S8 && input == FMT_S16_BE))) || + (!IS_BIG_ENDIAN && + ((output == FMT_U8 && input == FMT_U16_LE) || + (output == FMT_S8 && input == FMT_S16_LE)))) + return convert_to_8_native_endian; + + if ((IS_BIG_ENDIAN && + ((output == FMT_U8 && input == FMT_S16_BE) || + (output == FMT_S8 && input == FMT_U16_BE))) || + (!IS_BIG_ENDIAN && + ((output == FMT_U8 && input == FMT_S16_LE) || + (output == FMT_S8 && input == FMT_U16_LE)))) + return convert_to_8_native_endian_swap_sign; + + if ((!IS_BIG_ENDIAN && + ((output == FMT_U8 && input == FMT_U16_BE) || + (output == FMT_S8 && input == FMT_S16_BE))) || + (IS_BIG_ENDIAN && + ((output == FMT_U8 && input == FMT_U16_LE) || + (output == FMT_S8 && input == FMT_S16_LE)))) + return convert_to_8_alien_endian; + + if ((!IS_BIG_ENDIAN && + ((output == FMT_U8 && input == FMT_S16_BE) || + (output == FMT_S8 && input == FMT_U16_BE))) || + (IS_BIG_ENDIAN && + ((output == FMT_U8 && input == FMT_S16_LE) || + (output == FMT_S8 && input == FMT_U16_LE)))) + return convert_to_8_alien_endian_swap_sign; + + if ((output == FMT_U8 && input == FMT_S8) || + (output == FMT_S8 && input == FMT_U8)) + return convert_swap_sign8; + + if ((IS_BIG_ENDIAN && + ((output == FMT_U16_BE && input == FMT_U8) || + (output == FMT_S16_BE && input == FMT_S8))) || + (!IS_BIG_ENDIAN && + ((output == FMT_U16_LE && input == FMT_U8) || + (output == FMT_S16_LE && input == FMT_S8)))) + return convert_to_16_native_endian; + + if ((IS_BIG_ENDIAN && + ((output == FMT_U16_BE && input == FMT_S8) || + (output == FMT_S16_BE && input == FMT_U8))) || + (!IS_BIG_ENDIAN && + ((output == FMT_U16_LE && input == FMT_S8) || + (output == FMT_S16_LE && input == FMT_U8)))) + return convert_to_16_native_endian_swap_sign; + + if ((!IS_BIG_ENDIAN && + ((output == FMT_U16_BE && input == FMT_U8) || + (output == FMT_S16_BE && input == FMT_S8))) || + (IS_BIG_ENDIAN && + ((output == FMT_U16_LE && input == FMT_U8) || + (output == FMT_S16_LE && input == FMT_S8)))) + return convert_to_16_alien_endian; + + if ((!IS_BIG_ENDIAN && + ((output == FMT_U16_BE && input == FMT_S8) || + (output == FMT_S16_BE && input == FMT_U8))) || + (IS_BIG_ENDIAN && + ((output == FMT_U16_LE && input == FMT_S8) || + (output == FMT_S16_LE && input == FMT_U8)))) + return convert_to_16_alien_endian_swap_sign; + + g_warning("Translation needed, but not available.\n" + "Input: %d; Output %d.", input, output); + return NULL; +} + +static int +convert_mono_to_stereo(struct xmms_convert_buffers *buf, + void **data, int length, int b16) +{ + int i; + void *outbuf = convert_get_buffer(&buf->stereo_buffer, length * 2); + + if (b16) { + guint16 *output = outbuf, *input = *data; + for (i = 0; i < length / 2; i++) { + *output++ = *input; + *output++ = *input; + input++; + } + } + else { + guint8 *output = outbuf, *input = *data; + for (i = 0; i < length; i++) { + *output++ = *input; + *output++ = *input; + input++; + } + } + *data = outbuf; + + return length * 2; +} + +static int +convert_mono_to_stereo_8(struct xmms_convert_buffers *buf, + void **data, int length) +{ + return convert_mono_to_stereo(buf, data, length, FALSE); +} + +static int +convert_mono_to_stereo_16(struct xmms_convert_buffers *buf, + void **data, int length) +{ + return convert_mono_to_stereo(buf, data, length, TRUE); +} + +static int +convert_stereo_to_mono_u8(struct xmms_convert_buffers *buf, + void **data, int length) +{ + guint8 *output = *data, *input = *data; + int i; + for (i = 0; i < length / 2; i++) { + guint16 tmp; + tmp = *input++; + tmp += *input++; + *output++ = tmp / 2; + } + return length / 2; +} +static int +convert_stereo_to_mono_s8(struct xmms_convert_buffers *buf, + void **data, int length) +{ + gint8 *output = *data, *input = *data; + int i; + for (i = 0; i < length / 2; i++) { + gint16 tmp; + tmp = *input++; + tmp += *input++; + *output++ = tmp / 2; + } + return length / 2; +} +static int +convert_stereo_to_mono_u16le(struct xmms_convert_buffers *buf, + void **data, int length) +{ + guint16 *output = *data, *input = *data; + int i; + for (i = 0; i < length / 4; i++) { + guint32 tmp; + guint16 stmp; + tmp = GUINT16_FROM_LE(*input); + input++; + tmp += GUINT16_FROM_LE(*input); + input++; + stmp = tmp / 2; + *output++ = GUINT16_TO_LE(stmp); + } + return length / 2; +} + +static int +convert_stereo_to_mono_u16be(struct xmms_convert_buffers *buf, + void **data, int length) +{ + guint16 *output = *data, *input = *data; + int i; + for (i = 0; i < length / 4; i++) { + guint32 tmp; + guint16 stmp; + tmp = GUINT16_FROM_BE(*input); + input++; + tmp += GUINT16_FROM_BE(*input); + input++; + stmp = tmp / 2; + *output++ = GUINT16_TO_BE(stmp); + } + return length / 2; +} + +static int +convert_stereo_to_mono_s16le(struct xmms_convert_buffers *buf, + void **data, int length) +{ + gint16 *output = *data, *input = *data; + int i; + for (i = 0; i < length / 4; i++) { + gint32 tmp; + gint16 stmp; + tmp = GINT16_FROM_LE(*input); + input++; + tmp += GINT16_FROM_LE(*input); + input++; + stmp = tmp / 2; + *output++ = GINT16_TO_LE(stmp); + } + return length / 2; +} + +static int +convert_stereo_to_mono_s16be(struct xmms_convert_buffers *buf, + void **data, int length) +{ + gint16 *output = *data, *input = *data; + int i; + for (i = 0; i < length / 4; i++) { + gint32 tmp; + gint16 stmp; + tmp = GINT16_FROM_BE(*input); + input++; + tmp += GINT16_FROM_BE(*input); + input++; + stmp = tmp / 2; + *output++ = GINT16_TO_BE(stmp); + } + return length / 2; +} + +/** + * xmms_convert_get_channel_func: + * @fmt: The format of the data. + * @output: The number of channels to output as. + * @input: The number of channels inbound. + * + * Looks up the proper conversion method to use. + * + * Return value: A function pointer to the desired conversion function. + **/ +convert_channel_func_t +xmms_convert_get_channel_func(AFormat fmt, int output, int input) +{ + fmt = unnativize(fmt); + + if (output == input) + return NULL; + + if (input == 1 && output == 2) + switch (fmt) { + case FMT_U8: + case FMT_S8: + return convert_mono_to_stereo_8; + case FMT_U16_LE: + case FMT_U16_BE: + case FMT_S16_LE: + case FMT_S16_BE: + return convert_mono_to_stereo_16; + default: + g_warning("Unknown format: %d" "No conversion available.", fmt); + return NULL; + } + if (input == 2 && output == 1) + switch (fmt) { + case FMT_U8: + return convert_stereo_to_mono_u8; + case FMT_S8: + return convert_stereo_to_mono_s8; + case FMT_U16_LE: + return convert_stereo_to_mono_u16le; + case FMT_U16_BE: + return convert_stereo_to_mono_u16be; + case FMT_S16_LE: + return convert_stereo_to_mono_s16le; + case FMT_S16_BE: + return convert_stereo_to_mono_s16be; + default: + g_warning("Unknown format: %d. " + "No conversion available.", fmt); + return NULL; + + } + + g_warning("Input has %d channels, soundcard uses %d channels\n" + "No conversion is available", input, output); + return NULL; +} + + +#define RESAMPLE_STEREO(sample_type, bswap) \ + const int shift = sizeof (sample_type); \ + int i, in_samples, out_samples, x, delta; \ + sample_type *inptr = *data, *outptr; \ + guint nlen = (((length >> shift) * ofreq) / ifreq); \ + void *nbuf; \ + if (nlen == 0) \ + return 0; \ + nlen <<= shift; \ + if (bswap) \ + convert_swap_endian(NULL, data, length); \ + nbuf = convert_get_buffer(&buf->freq_buffer, nlen); \ + outptr = nbuf; \ + in_samples = length >> shift; \ + out_samples = nlen >> shift; \ + delta = (in_samples << 12) / out_samples; \ + for (x = 0, i = 0; i < out_samples; i++) \ + { \ + int x1, frac; \ + x1 = (x >> 12) << 12; \ + frac = x - x1; \ + *outptr++ = \ + ((inptr[(x1 >> 12) << 1] * \ + ((1<<12) - frac) + \ + inptr[((x1 >> 12) + 1) << 1] * \ + frac) >> 12); \ + *outptr++ = \ + ((inptr[((x1 >> 12) << 1) + 1] * \ + ((1<<12) - frac) + \ + inptr[(((x1 >> 12) + 1) << 1) + 1] * \ + frac) >> 12); \ + x += delta; \ + } \ + if (bswap) \ + convert_swap_endian(NULL, &nbuf, nlen); \ + *data = nbuf; \ + return nlen; \ + + +#define RESAMPLE_MONO(sample_type, bswap) \ + const int shift = sizeof (sample_type) - 1; \ + int i, x, delta, in_samples, out_samples; \ + sample_type *inptr = *data, *outptr; \ + guint nlen = (((length >> shift) * ofreq) / ifreq); \ + void *nbuf; \ + if (nlen == 0) \ + return 0; \ + nlen <<= shift; \ + if (bswap) \ + convert_swap_endian(NULL, data, length); \ + nbuf = convert_get_buffer(&buf->freq_buffer, nlen); \ + outptr = nbuf; \ + in_samples = length >> shift; \ + out_samples = nlen >> shift; \ + delta = ((length >> shift) << 12) / out_samples; \ + for (x = 0, i = 0; i < out_samples; i++) \ + { \ + int x1, frac; \ + x1 = (x >> 12) << 12; \ + frac = x - x1; \ + *outptr++ = \ + ((inptr[x1 >> 12] * ((1<<12) - frac) + \ + inptr[(x1 >> 12) + 1] * frac) >> 12); \ + x += delta; \ + } \ + if (bswap) \ + convert_swap_endian(NULL, &nbuf, nlen); \ + *data = nbuf; \ + return nlen; \ + +static int +convert_resample_stereo_s16ne(struct xmms_convert_buffers *buf, + void **data, int length, int ifreq, int ofreq) +{ + RESAMPLE_STEREO(gint16, FALSE); +} + +static int +convert_resample_stereo_s16ae(struct xmms_convert_buffers *buf, + void **data, int length, int ifreq, int ofreq) +{ + RESAMPLE_STEREO(gint16, TRUE); +} + +static int +convert_resample_stereo_u16ne(struct xmms_convert_buffers *buf, + void **data, int length, int ifreq, int ofreq) +{ + RESAMPLE_STEREO(guint16, FALSE); +} + +static int +convert_resample_stereo_u16ae(struct xmms_convert_buffers *buf, + void **data, int length, int ifreq, int ofreq) +{ + RESAMPLE_STEREO(guint16, TRUE); +} + +static int +convert_resample_mono_s16ne(struct xmms_convert_buffers *buf, + void **data, int length, int ifreq, int ofreq) +{ + RESAMPLE_MONO(gint16, FALSE); +} + +static int +convert_resample_mono_s16ae(struct xmms_convert_buffers *buf, + void **data, int length, int ifreq, int ofreq) +{ + RESAMPLE_MONO(gint16, TRUE); +} + +static int +convert_resample_mono_u16ne(struct xmms_convert_buffers *buf, + void **data, int length, int ifreq, int ofreq) +{ + RESAMPLE_MONO(guint16, FALSE); +} + +static int +convert_resample_mono_u16ae(struct xmms_convert_buffers *buf, + void **data, int length, int ifreq, int ofreq) +{ + RESAMPLE_MONO(guint16, TRUE); +} + +static int +convert_resample_stereo_u8(struct xmms_convert_buffers *buf, + void **data, int length, int ifreq, int ofreq) +{ + RESAMPLE_STEREO(guint8, FALSE); +} + +static int +convert_resample_mono_u8(struct xmms_convert_buffers *buf, + void **data, int length, int ifreq, int ofreq) +{ + RESAMPLE_MONO(guint8, FALSE); +} + +static int +convert_resample_stereo_s8(struct xmms_convert_buffers *buf, + void **data, int length, int ifreq, int ofreq) +{ + RESAMPLE_STEREO(gint8, FALSE); +} + +static int +convert_resample_mono_s8(struct xmms_convert_buffers *buf, + void **data, int length, int ifreq, int ofreq) +{ + RESAMPLE_MONO(gint8, FALSE); +} + + +/** + * xmms_convert_get_frequency_func: + * @fmt: The format of the data. + * @channels: The number of channels inbound. + * + * Looks up the proper conversion method to use. + * + * Return value: A function pointer to the desired conversion function. + **/ +convert_freq_func_t +xmms_convert_get_frequency_func(AFormat fmt, int channels) +{ + fmt = unnativize(fmt); + g_message("fmt %d, channels: %d", fmt, channels); + + if (channels < 1 || channels > 2) { + g_warning("Unsupported number of channels: %d. " + "Resample function not available", channels); + return NULL; + } + if ((IS_BIG_ENDIAN && fmt == FMT_U16_BE) || + (!IS_BIG_ENDIAN && fmt == FMT_U16_LE)) { + if (channels == 1) + return convert_resample_mono_u16ne; + else + return convert_resample_stereo_u16ne; + } + if ((IS_BIG_ENDIAN && fmt == FMT_S16_BE) || + (!IS_BIG_ENDIAN && fmt == FMT_S16_LE)) { + if (channels == 1) + return convert_resample_mono_s16ne; + else + return convert_resample_stereo_s16ne; + } + if ((!IS_BIG_ENDIAN && fmt == FMT_U16_BE) || + (IS_BIG_ENDIAN && fmt == FMT_U16_LE)) { + if (channels == 1) + return convert_resample_mono_u16ae; + else + return convert_resample_stereo_u16ae; + } + if ((!IS_BIG_ENDIAN && fmt == FMT_S16_BE) || + (IS_BIG_ENDIAN && fmt == FMT_S16_LE)) { + if (channels == 1) + return convert_resample_mono_s16ae; + else + return convert_resample_stereo_s16ae; + } + if (fmt == FMT_U8) { + if (channels == 1) + return convert_resample_mono_u8; + else + return convert_resample_stereo_u8; + } + if (fmt == FMT_S8) { + if (channels == 1) + return convert_resample_mono_s8; + else + return convert_resample_stereo_s8; + } + g_warning("Resample function not available" "Format %d.", fmt); + return NULL; +} diff -r 4e2fc64d95ef -r 3ec22a11c83e src/audacious/xconvert.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/audacious/xconvert.h Sat Jan 27 12:10:21 2007 -0800 @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2003 Haavard Kvaalen + * + * Licensed under GNU LGPL version 2. + */ + +#include + +struct xmms_convert_buffers; + +struct xmms_convert_buffers *xmms_convert_buffers_new(void); +/* + * Free the data assosiated with the buffers, without destroying the + * context. The context can be reused. + */ +void xmms_convert_buffers_free(struct xmms_convert_buffers *buf); +void xmms_convert_buffers_destroy(struct xmms_convert_buffers *buf); + + +typedef int (*convert_func_t) (struct xmms_convert_buffers * buf, + void **data, int length); +typedef int (*convert_channel_func_t) (struct xmms_convert_buffers * buf, + void **data, int length); +typedef int (*convert_freq_func_t) (struct xmms_convert_buffers * buf, + void **data, int length, int ifreq, + int ofreq); + + +convert_func_t xmms_convert_get_func(AFormat output, AFormat input); +convert_channel_func_t xmms_convert_get_channel_func(AFormat fmt, + int output, + int input); +convert_freq_func_t xmms_convert_get_frequency_func(AFormat fmt, + int channels); diff -r 4e2fc64d95ef -r 3ec22a11c83e src/libaudacious/Makefile --- a/src/libaudacious/Makefile Sat Jan 27 11:40:05 2007 -0800 +++ b/src/libaudacious/Makefile Sat Jan 27 12:10:21 2007 -0800 @@ -7,16 +7,16 @@ OBJECTIVE_SONAME_SUFFIX = 4 LIBADD = \ - $(GTK_LIBS) \ - $(GCONF_LIBS) \ + $(GTK_LIBS) \ + $(GCONF_LIBS) \ $(LIBMCS_LIBS) CFLAGS += $(PICFLAGS) \ - $(GTK_CFLAGS) \ - $(GCONF_CFLAGS) \ - $(LIBMCS_CFLAGS) \ - -D_AUDACIOUS_CORE \ - -I.. -I../.. \ + $(GTK_CFLAGS) \ + $(GCONF_CFLAGS) \ + $(LIBMCS_CFLAGS) \ + -D_AUDACIOUS_CORE \ + -I.. -I../.. \ -I../intl CONF_SRC = configdb_$(CONFIGDB_BACKEND).c @@ -24,18 +24,14 @@ SOURCES = \ $(CONF_SRC) \ rcfile.c \ - beepctrl.c \ - titlestring.c \ - xconvert.c + beepctrl.c OBJECTS = ${SOURCES:.c=.o} HEADERS = \ rcfile.h \ configdb.h \ - beepctrl.h \ - titlestring.h \ - xconvert.h + beepctrl.h include ../../mk/objective.mk diff -r 4e2fc64d95ef -r 3ec22a11c83e src/libaudacious/titlestring.c --- a/src/libaudacious/titlestring.c Sat Jan 27 11:40:05 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,449 +0,0 @@ -/* - * Copyright (C) 2001, Espen Skoglund - * Copyright (C) 2001, Haavard Kvaalen - * - * 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. - * - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#define GETTEXT_PACKAGE PACKAGE_NAME - -#include -#include -#include -#include -#include - -#include "titlestring.h" - -#define CHECK(input, field) \ - (((gchar *) &input->field - (gchar *) input) < input->__size) - -#define VS(input, field) (CHECK(input, field) ? input->field : NULL) -#define VI(input, field) (CHECK(input, field) ? input->field : 0) - -/** - * bmp_title_input_new: - * - * #BmpTitleInput tuple factory. - * - * Return value: A #BmpTitleInput object. - **/ -BmpTitleInput * -bmp_title_input_new() -{ - BmpTitleInput *input; - input = g_new0(BmpTitleInput, 1); - input->__size = XMMS_TITLEINPUT_SIZE; - input->__version = XMMS_TITLEINPUT_VERSION; - return input; -} - -/** - * bmp_title_input_free: - * @input: A #BmpTitleInput tuple to destroy. - * - * Destroys a #BmpTitleInput tuple. - **/ -void -bmp_title_input_free(BmpTitleInput * input) -{ - if (input == NULL) - return; - - if (input->performer != NULL) - g_free(input->performer); - - if (input->album_name != NULL) - g_free(input->album_name); - - if (input->track_name != NULL) - g_free(input->track_name); - - if (input->date != NULL) - g_free(input->date); - - if (input->genre != NULL) - g_free(input->genre); - - if (input->comment != NULL) - g_free(input->comment); - - if (input->file_name != NULL) - g_free(input->file_name); - - if (input->file_path != NULL) - g_free(input->file_path); - - g_free(input); -} - -/** - * xmms_get_titlestring: - * @fmt: A format string. - * @input: A tuple to use for data. - * - * Generates a formatted string from a tuple. - * - * Return value: A formatted tuple string. - **/ -gchar * -xmms_get_titlestring(const gchar * fmt, TitleInput * input) -{ - GString *outstr; - const gchar *string; - gchar c, convert[16]; - gint numdigits, numpr, val, i; - gint f_left, f_space, f_zero, someflag, width, precision; - gboolean did_output = FALSE; - gchar digits[] = "0123456789"; - -#define PUTCH(ch) g_string_append_c(outstr, ch) - -#define LEFTPAD(num) \ - G_STMT_START { \ - gint cnt = (num); \ - if ( ! f_left && cnt > 0 ) \ - while ( cnt-- > 0 ) \ - PUTCH(f_zero ? '0' : ' '); \ - } G_STMT_END; - -#define RIGHTPAD(num) \ - G_STMT_START { \ - gint cnt = (num); \ - if ( f_left && cnt > 0 ) \ - while ( cnt-- > 0 ) \ - PUTCH( ' ' ); \ - } G_STMT_END; - - if (fmt == NULL || input == NULL) - return NULL; - outstr = g_string_new(""); - - for (;;) { - /* Copy characters until we encounter '%'. */ - while ((c = *fmt++) != '%') { - if (c == '\0') - goto Done; - g_string_append_c(outstr, c); - } - - f_left = f_space = f_zero = 0; - someflag = 1; - - - /* Parse flags. */ - while (someflag) { - switch (*fmt) { - case '-': - f_left = 1; - fmt++; - break; - case ' ': - f_space = 1; - fmt++; - break; - case '0': - f_zero = 1; - fmt++; - break; - default: - someflag = 0; - break; - } - } - - - /* Parse field width. */ - if ((c = *fmt) >= '0' && c <= '9') { - width = 0; - while ((c = *fmt++) >= '0' && c <= '9') { - width *= 10; - width += c - '0'; - } - fmt--; - } - else - width = -1; - - - /* Parse precision. */ - if (*fmt == '.') { - if ((c = *++fmt) >= '0' && c <= '9') { - precision = 0; - while ((c = *fmt++) >= '0' && c <= '9') { - precision *= 10; - precision += c - '0'; - } - fmt--; - } - else - precision = -1; - } - else - precision = -1; - - - /* Parse format conversion. */ - switch (c = *fmt++) { - case '}': /* close optional, just ignore */ - continue; - - case '{':{ /* optional entry: %{n:...%} */ - char n = *fmt++; - if (!((n == 'a' && VS(input, album_name)) || - (n == 'c' && VS(input, comment)) || - (n == 'd' && VS(input, date)) || - (n == 'e' && VS(input, file_ext)) || - (n == 'f' && VS(input, file_name)) || - (n == 'F' && VS(input, file_path)) || - (n == 'g' && VS(input, genre)) || - (n == 'n' && VI(input, track_number)) || - (n == 'p' && VS(input, performer)) || - (n == 't' && VS(input, track_name)) || - (n == 'y' && VI(input, year)))) { - int nl = 0; - char c; - while ((c = *fmt++)) /* until end of string */ - if (c == '}') /* if end of opt */ - if (!nl) - break; /* if outmost indent level */ - else - --nl; /* else reduce indent */ - else if (c == '{') - ++nl; /* increase indent */ - } - else - ++fmt; - break; - } - - case 'a': - string = VS(input, album_name); - goto Print_string; - case 'c': - string = VS(input, comment); - goto Print_string; - case 'd': - string = VS(input, date); - goto Print_string; - case 'e': - string = VS(input, file_ext); - goto Print_string; - case 'f': - string = VS(input, file_name); - goto Print_string; - case 'F': - string = VS(input, file_path); - goto Print_string; - case 'g': - string = VS(input, genre); - goto Print_string; - case 'n': - val = VI(input, track_number); - goto Print_number; - case 'p': - string = VS(input, performer); - goto Print_string; - case 't': - string = VS(input, track_name); - goto Print_string; - case 'y': - val = VI(input, year); - goto Print_number; - - Print_string: - if (string == NULL) - break; - did_output = TRUE; - - numpr = 0; - if (width > 0) { - /* Calculate printed size. */ - numpr = strlen(string); - if (precision >= 0 && precision < numpr) - numpr = precision; - - LEFTPAD(width - numpr); - } - - /* Insert string. */ - if (precision >= 0) { - glong offset_max = precision, offset; - gchar *uptr = NULL; - const gchar *tmpstring = string; - while (precision > 0) { - offset = offset_max - precision; - uptr = g_utf8_offset_to_pointer(tmpstring, offset); - if (*uptr == '\0') - break; - g_string_append_unichar(outstr, g_utf8_get_char(uptr)); - precision--; - } - } - else { - while ((c = *string++) != '\0') - PUTCH(c); - } - - RIGHTPAD(width - numpr); - break; - - Print_number: - if (val == 0) - break; - if (c != 'N') - did_output = TRUE; - - /* Create reversed number string. */ - numdigits = 0; - do { - convert[numdigits++] = digits[val % 10]; - val /= 10; - } - while (val > 0); - - numpr = numdigits > precision ? numdigits : precision; - - /* Insert left padding. */ - if (!f_left && width > numpr) { - if (f_zero) - numpr = width; - else - for (i = width - numpr; i-- > 0;) - PUTCH(' '); - } - - /* Insert zero padding. */ - for (i = numpr - numdigits; i-- > 0;) - PUTCH('0'); - - /* Insert number. */ - while (numdigits > 0) - PUTCH(convert[--numdigits]); - - RIGHTPAD(width - numpr); - break; - - case '%': - PUTCH('%'); - break; - - default: - PUTCH('%'); - PUTCH(c); - break; - } - } - - Done: - if (did_output) - return g_string_free(outstr, FALSE); - else - return NULL; -} - -struct _TagDescription { - gchar tag; - gchar *description; -}; - -typedef struct _TagDescription TagDescription; - -static TagDescription tag_descriptions[] = { - {'p', N_("Performer/Artist")}, - {'a', N_("Album")}, - {'g', N_("Genre")}, - {'f', N_("File name")}, - {'F', N_("File path")}, - {'e', N_("File extension")}, - {'t', N_("Track name")}, - {'n', N_("Track number")}, - {'d', N_("Date")}, - {'y', N_("Year")}, - {'c', N_("Comment")} -}; - -gint tag_descriptions_length = - sizeof(tag_descriptions) / sizeof(TagDescription); - -/** - * xmms_titlestring_descriptions: - * @tags: A list of formatters to provide. - * @columns: A number of columns to arrange them in. - * - * Generates a box explaining how to use the formatters. - * - * Return value: A GtkWidget containing the table. - **/ -GtkWidget * -xmms_titlestring_descriptions(gchar * tags, gint columns) -{ - GtkWidget *table, *label; - gchar tag_str[5]; - gint num = strlen(tags); - gint r = 0, c, i; - - g_return_val_if_fail(tags != NULL, NULL); - g_return_val_if_fail(columns <= num, NULL); - - table = gtk_table_new((num + columns - 1) / columns, columns * 2, FALSE); - gtk_table_set_row_spacings(GTK_TABLE(table), 2); - gtk_table_set_col_spacings(GTK_TABLE(table), 5); - - for (c = 0; c < columns; c++) { - for (r = 0; r < (num + columns - 1 - c) / columns; r++) { - g_snprintf(tag_str, sizeof(tag_str), "%%%c:", *tags); - label = gtk_label_new(tag_str); - gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); - gtk_table_attach(GTK_TABLE(table), label, 2 * c, 2 * c + 1, r, - r + 1, GTK_FILL, GTK_FILL, 0, 0); - gtk_widget_show(label); - - for (i = 0; i < tag_descriptions_length; i++) { - if (*tags == tag_descriptions[i].tag) { - label = gtk_label_new(_(tag_descriptions[i].description)); - gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); - gtk_table_attach(GTK_TABLE(table), label, 2 * c + 1, - 2 * c + 2, r, r + 1, - GTK_EXPAND | GTK_FILL, - GTK_EXPAND | GTK_FILL, 0, 0); - gtk_widget_show(label); - break; - } - } - - if (i == tag_descriptions_length) - g_warning("Invalid tag: %c", *tags); - - tags++; - } - - } - - label = gtk_label_new(_("%{n:...%}: Display \"...\" only if element " - "%n is present")); - gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5); - gtk_table_attach(GTK_TABLE(table), label, 0, r + 1, - r + 1, r + 2, GTK_FILL, GTK_FILL, 0, 0); - gtk_widget_show(label); - - return table; -} diff -r 4e2fc64d95ef -r 3ec22a11c83e src/libaudacious/titlestring.h --- a/src/libaudacious/titlestring.h Sat Jan 27 11:40:05 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,120 +0,0 @@ -/* - * Copyright (C) 2001, Espen Skoglund - * - * 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 XMMS_TITLESTRING_H -#define XMMS_TITLESTRING_H - -#include -#include -#include -#include - -/** - * TitleInput: - * @__size: Private field which describes the version of the TitleInput. - * @__version: Private field which describes the version of the TitleInput. - * @performer: The performer of the media that the tuple is describing. - * @album_name: The name of the album that contains the media. - * @track_name: The title of the media. - * @track_number: The track number of the media. - * @year: The year the media was published. - * @date: The date the media was published. - * @genre: The genre of the media. - * @comment: Any comments attached to the media. - * @file_name: The filename which refers to the media. - * @file_ext: The file's extension. - * @file_path: The path that the media is in. - * @length: The length of the media. - * @formatter: The format string that should be used. - * @mtime: The last modified time of the file. - * - * Tuple which is passed to xmms_get_titlestring(). An input tuple - * is allocated and initialized with bmp_title_input_new(). Before - * passing the struct to xmms_get_titlestring() it should be filled - * with appropriate field values. - **/ -typedef struct { - gint __size; /* Set by bmp_title_input_new() */ - gint __version; /* Ditto */ - - gchar *performer; /* %p */ - gchar *album_name; /* %a */ - gchar *track_name; /* %t */ - gint track_number; /* %n */ - gint year; /* %y */ - gchar *date; /* %d */ - gchar *genre; /* %g */ - gchar *comment; /* %c */ - gchar *file_name; /* %f */ - const gchar *file_ext; /* %e *//* is not always strdup'ed, see xmms_input_get_song_info and plugins! */ - gchar *file_path; /* %F */ - gint length; /* not displayable */ - gchar *formatter; /* not displayable */ - time_t mtime; -} TitleInput; - -/** - * BmpTitleInput: - * - * An alternate name for the #TitleInput object. - **/ -typedef TitleInput BmpTitleInput; - - -/* - * Using a __size field helps the library functions detect plugins - * that use a possibly extended version of the struct. The __version - * field helps the library detect possible future incompatibilities in - * the struct layout. - */ - -/** - * XMMS_TITLEINPUT_SIZE: - * - * The size of the TitleInput object compiled into the library. - **/ -#define XMMS_TITLEINPUT_SIZE sizeof(TitleInput) - -/** - * XMMS_TITLEINPUT_VERSION: - * - * The version of the TitleInput object compiled into the library. - **/ -#define XMMS_TITLEINPUT_VERSION (1) - -/** - * XMMS_NEW_TITLEINPUT: - * @input: A TitleInput to initialize. - * - * Initializes a TitleInput object. Included for XMMS compatibility. - **/ -#define XMMS_NEW_TITLEINPUT(input) input = bmp_title_input_new(); - - -G_BEGIN_DECLS - -TitleInput *bmp_title_input_new(void); -void bmp_title_input_free(BmpTitleInput * input); - -gchar *xmms_get_titlestring(const gchar * fmt, TitleInput * input); -GtkWidget *xmms_titlestring_descriptions(gchar * tags, gint columns); - -G_END_DECLS - -#endif /* !XMMS_TITLESTRING_H */ diff -r 4e2fc64d95ef -r 3ec22a11c83e src/libaudacious/xconvert.c --- a/src/libaudacious/xconvert.c Sat Jan 27 11:40:05 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,849 +0,0 @@ -/* Audacious - * Copyright (C) 2005-2007 Audacious team - * - * XMMS - Cross-platform multimedia player - * Copyright (C) 1998-2003 Peter Alm, Mikael Alm, Olle Hallnas, - * Thomas Nilsson and 4Front Technologies - * Copyright (C) 1999-2003 Haavard Kvaalen - * - * 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 2 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, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "config.h" -#include -#include -#include "xconvert.h" - -#define IS_BIG_ENDIAN (G_BYTE_ORDER==G_BIG_ENDIAN) - -/** - * buffer: - * - * Contains data for conversion. - * - * @buffer: A pointer to the memory being used in the conversion process. - * @size: The size of the memory being referenced. - **/ -struct buffer { - void *buffer; - int size; -}; - -/** - * xmms_convert_buffers: - * - * Stores data for conversion. - * - * @format_buffer: A buffer for converting formats. - * @stereo_buffer: A buffer for downmixing or upmixing. - * @freq_buffer: A buffer used for resampling. - **/ -struct xmms_convert_buffers { - struct buffer format_buffer, stereo_buffer, freq_buffer; -}; - -/** - * xmms_convert_buffers_new: - * - * Factory for an #xmms_convert_buffers struct. - * - * Return value: An #xmms_convert_buffers struct. - **/ -struct xmms_convert_buffers * -xmms_convert_buffers_new(void) -{ - return g_malloc0(sizeof(struct xmms_convert_buffers)); -} - -/** - * convert_get_buffer: - * @buffer: A buffer to resize. - * @size: The new size for that buffer. - * - * Resizes a conversion buffer. - **/ -static void * -convert_get_buffer(struct buffer *buffer, size_t size) -{ - if (size > 0 && size <= (size_t)buffer->size) - return buffer->buffer; - - buffer->size = size; - buffer->buffer = g_realloc(buffer->buffer, size); - return buffer->buffer; -} - -/** - * xmms_convert_buffers_free: - * @buf: An xmms_convert_buffers structure to free. - * - * Frees the actual buffers contained inside the buffer struct. - **/ -void -xmms_convert_buffers_free(struct xmms_convert_buffers *buf) -{ - convert_get_buffer(&buf->format_buffer, 0); - convert_get_buffer(&buf->stereo_buffer, 0); - convert_get_buffer(&buf->freq_buffer, 0); -} - -/** - * xmms_convert_buffers_destroy: - * @buf: An xmms_convert_buffers structure to destroy. - * - * Destroys an xmms_convert_buffers structure. - **/ -void -xmms_convert_buffers_destroy(struct xmms_convert_buffers *buf) -{ - if (!buf) - return; - xmms_convert_buffers_free(buf); - g_free(buf); -} - -static int -convert_swap_endian(struct xmms_convert_buffers *buf, void **data, int length) -{ - guint16 *ptr = *data; - int i; - for (i = 0; i < length; i += 2, ptr++) - *ptr = GUINT16_SWAP_LE_BE(*ptr); - - return i; -} - -static int -convert_swap_sign_and_endian_to_native(struct - xmms_convert_buffers - *buf, void **data, int length) -{ - guint16 *ptr = *data; - int i; - for (i = 0; i < length; i += 2, ptr++) - *ptr = GUINT16_SWAP_LE_BE(*ptr) ^ 1 << 15; - - return i; -} - -static int -convert_swap_sign_and_endian_to_alien(struct - xmms_convert_buffers *buf, - void **data, int length) -{ - guint16 *ptr = *data; - int i; - for (i = 0; i < length; i += 2, ptr++) - *ptr = GUINT16_SWAP_LE_BE(*ptr ^ 1 << 15); - - return i; -} - -static int -convert_swap_sign16(struct xmms_convert_buffers *buf, void **data, int length) -{ - gint16 *ptr = *data; - int i; - for (i = 0; i < length; i += 2, ptr++) - *ptr ^= 1 << 15; - - return i; -} - -static int -convert_swap_sign8(struct xmms_convert_buffers *buf, void **data, int length) -{ - gint8 *ptr = *data; - int i; - for (i = 0; i < length; i++) - *ptr++ ^= 1 << 7; - - return i; -} - -static int -convert_to_8_native_endian(struct xmms_convert_buffers *buf, - void **data, int length) -{ - gint8 *output = *data; - gint16 *input = *data; - int i; - for (i = 0; i < length / 2; i++) - *output++ = *input++ >> 8; - - return i; -} - -static int -convert_to_8_native_endian_swap_sign(struct xmms_convert_buffers - *buf, void **data, int length) -{ - gint8 *output = *data; - gint16 *input = *data; - int i; - for (i = 0; i < length / 2; i++) - *output++ = (*input++ >> 8) ^ (1 << 7); - - return i; -} - - -static int -convert_to_8_alien_endian(struct xmms_convert_buffers *buf, - void **data, int length) -{ - gint8 *output = *data; - gint16 *input = *data; - int i; - for (i = 0; i < length / 2; i++) - *output++ = *input++ & 0xff; - - return i; -} - -static int -convert_to_8_alien_endian_swap_sign(struct xmms_convert_buffers - *buf, void **data, int length) -{ - gint8 *output = *data; - gint16 *input = *data; - int i; - for (i = 0; i < length / 2; i++) - *output++ = (*input++ & 0xff) ^ (1 << 7); - - return i; -} - -static int -convert_to_16_native_endian(struct xmms_convert_buffers *buf, - void **data, int length) -{ - guint8 *input = *data; - guint16 *output; - int i; - *data = convert_get_buffer(&buf->format_buffer, length * 2); - output = *data; - for (i = 0; i < length; i++) - *output++ = *input++ << 8; - - return i * 2; -} - -static int -convert_to_16_native_endian_swap_sign(struct - xmms_convert_buffers *buf, - void **data, int length) -{ - guint8 *input = *data; - guint16 *output; - int i; - *data = convert_get_buffer(&buf->format_buffer, length * 2); - output = *data; - for (i = 0; i < length; i++) - *output++ = (*input++ << 8) ^ (1 << 15); - - return i * 2; -} - - -static int -convert_to_16_alien_endian(struct xmms_convert_buffers *buf, - void **data, int length) -{ - guint8 *input = *data; - guint16 *output; - int i; - *data = convert_get_buffer(&buf->format_buffer, length * 2); - output = *data; - for (i = 0; i < length; i++) - *output++ = *input++; - - return i * 2; -} - -static int -convert_to_16_alien_endian_swap_sign(struct xmms_convert_buffers - *buf, void **data, int length) -{ - guint8 *input = *data; - guint16 *output; - int i; - *data = convert_get_buffer(&buf->format_buffer, length * 2); - output = *data; - for (i = 0; i < length; i++) - *output++ = *input++ ^ (1 << 7); - - return i * 2; -} - -static AFormat -unnativize(AFormat fmt) -{ - if (fmt == FMT_S16_NE) { - if (IS_BIG_ENDIAN) - return FMT_S16_BE; - else - return FMT_S16_LE; - } - if (fmt == FMT_U16_NE) { - if (IS_BIG_ENDIAN) - return FMT_U16_BE; - else - return FMT_U16_LE; - } - return fmt; -} - -/** - * xmms_convert_get_func: - * @output: A format to output data as. - * @input: The format of the inbound data. - * - * Looks up the proper conversion method to use. - * - * Return value: A function pointer to the desired conversion function. - **/ -convert_func_t -xmms_convert_get_func(AFormat output, AFormat input) -{ - output = unnativize(output); - input = unnativize(input); - - if (output == input) - return NULL; - - if ((output == FMT_U16_BE && input == FMT_U16_LE) || - (output == FMT_U16_LE && input == FMT_U16_BE) || - (output == FMT_S16_BE && input == FMT_S16_LE) || - (output == FMT_S16_LE && input == FMT_S16_BE)) - return convert_swap_endian; - - if ((output == FMT_U16_BE && input == FMT_S16_BE) || - (output == FMT_U16_LE && input == FMT_S16_LE) || - (output == FMT_S16_BE && input == FMT_U16_BE) || - (output == FMT_S16_LE && input == FMT_U16_LE)) - return convert_swap_sign16; - - if ((IS_BIG_ENDIAN && - ((output == FMT_U16_BE && input == FMT_S16_LE) || - (output == FMT_S16_BE && input == FMT_U16_LE))) || - (!IS_BIG_ENDIAN && - ((output == FMT_U16_LE && input == FMT_S16_BE) || - (output == FMT_S16_LE && input == FMT_U16_BE)))) - return convert_swap_sign_and_endian_to_native; - - if ((!IS_BIG_ENDIAN && - ((output == FMT_U16_BE && input == FMT_S16_LE) || - (output == FMT_S16_BE && input == FMT_U16_LE))) || - (IS_BIG_ENDIAN && - ((output == FMT_U16_LE && input == FMT_S16_BE) || - (output == FMT_S16_LE && input == FMT_U16_BE)))) - return convert_swap_sign_and_endian_to_alien; - - if ((IS_BIG_ENDIAN && - ((output == FMT_U8 && input == FMT_U16_BE) || - (output == FMT_S8 && input == FMT_S16_BE))) || - (!IS_BIG_ENDIAN && - ((output == FMT_U8 && input == FMT_U16_LE) || - (output == FMT_S8 && input == FMT_S16_LE)))) - return convert_to_8_native_endian; - - if ((IS_BIG_ENDIAN && - ((output == FMT_U8 && input == FMT_S16_BE) || - (output == FMT_S8 && input == FMT_U16_BE))) || - (!IS_BIG_ENDIAN && - ((output == FMT_U8 && input == FMT_S16_LE) || - (output == FMT_S8 && input == FMT_U16_LE)))) - return convert_to_8_native_endian_swap_sign; - - if ((!IS_BIG_ENDIAN && - ((output == FMT_U8 && input == FMT_U16_BE) || - (output == FMT_S8 && input == FMT_S16_BE))) || - (IS_BIG_ENDIAN && - ((output == FMT_U8 && input == FMT_U16_LE) || - (output == FMT_S8 && input == FMT_S16_LE)))) - return convert_to_8_alien_endian; - - if ((!IS_BIG_ENDIAN && - ((output == FMT_U8 && input == FMT_S16_BE) || - (output == FMT_S8 && input == FMT_U16_BE))) || - (IS_BIG_ENDIAN && - ((output == FMT_U8 && input == FMT_S16_LE) || - (output == FMT_S8 && input == FMT_U16_LE)))) - return convert_to_8_alien_endian_swap_sign; - - if ((output == FMT_U8 && input == FMT_S8) || - (output == FMT_S8 && input == FMT_U8)) - return convert_swap_sign8; - - if ((IS_BIG_ENDIAN && - ((output == FMT_U16_BE && input == FMT_U8) || - (output == FMT_S16_BE && input == FMT_S8))) || - (!IS_BIG_ENDIAN && - ((output == FMT_U16_LE && input == FMT_U8) || - (output == FMT_S16_LE && input == FMT_S8)))) - return convert_to_16_native_endian; - - if ((IS_BIG_ENDIAN && - ((output == FMT_U16_BE && input == FMT_S8) || - (output == FMT_S16_BE && input == FMT_U8))) || - (!IS_BIG_ENDIAN && - ((output == FMT_U16_LE && input == FMT_S8) || - (output == FMT_S16_LE && input == FMT_U8)))) - return convert_to_16_native_endian_swap_sign; - - if ((!IS_BIG_ENDIAN && - ((output == FMT_U16_BE && input == FMT_U8) || - (output == FMT_S16_BE && input == FMT_S8))) || - (IS_BIG_ENDIAN && - ((output == FMT_U16_LE && input == FMT_U8) || - (output == FMT_S16_LE && input == FMT_S8)))) - return convert_to_16_alien_endian; - - if ((!IS_BIG_ENDIAN && - ((output == FMT_U16_BE && input == FMT_S8) || - (output == FMT_S16_BE && input == FMT_U8))) || - (IS_BIG_ENDIAN && - ((output == FMT_U16_LE && input == FMT_S8) || - (output == FMT_S16_LE && input == FMT_U8)))) - return convert_to_16_alien_endian_swap_sign; - - g_warning("Translation needed, but not available.\n" - "Input: %d; Output %d.", input, output); - return NULL; -} - -static int -convert_mono_to_stereo(struct xmms_convert_buffers *buf, - void **data, int length, int b16) -{ - int i; - void *outbuf = convert_get_buffer(&buf->stereo_buffer, length * 2); - - if (b16) { - guint16 *output = outbuf, *input = *data; - for (i = 0; i < length / 2; i++) { - *output++ = *input; - *output++ = *input; - input++; - } - } - else { - guint8 *output = outbuf, *input = *data; - for (i = 0; i < length; i++) { - *output++ = *input; - *output++ = *input; - input++; - } - } - *data = outbuf; - - return length * 2; -} - -static int -convert_mono_to_stereo_8(struct xmms_convert_buffers *buf, - void **data, int length) -{ - return convert_mono_to_stereo(buf, data, length, FALSE); -} - -static int -convert_mono_to_stereo_16(struct xmms_convert_buffers *buf, - void **data, int length) -{ - return convert_mono_to_stereo(buf, data, length, TRUE); -} - -static int -convert_stereo_to_mono_u8(struct xmms_convert_buffers *buf, - void **data, int length) -{ - guint8 *output = *data, *input = *data; - int i; - for (i = 0; i < length / 2; i++) { - guint16 tmp; - tmp = *input++; - tmp += *input++; - *output++ = tmp / 2; - } - return length / 2; -} -static int -convert_stereo_to_mono_s8(struct xmms_convert_buffers *buf, - void **data, int length) -{ - gint8 *output = *data, *input = *data; - int i; - for (i = 0; i < length / 2; i++) { - gint16 tmp; - tmp = *input++; - tmp += *input++; - *output++ = tmp / 2; - } - return length / 2; -} -static int -convert_stereo_to_mono_u16le(struct xmms_convert_buffers *buf, - void **data, int length) -{ - guint16 *output = *data, *input = *data; - int i; - for (i = 0; i < length / 4; i++) { - guint32 tmp; - guint16 stmp; - tmp = GUINT16_FROM_LE(*input); - input++; - tmp += GUINT16_FROM_LE(*input); - input++; - stmp = tmp / 2; - *output++ = GUINT16_TO_LE(stmp); - } - return length / 2; -} - -static int -convert_stereo_to_mono_u16be(struct xmms_convert_buffers *buf, - void **data, int length) -{ - guint16 *output = *data, *input = *data; - int i; - for (i = 0; i < length / 4; i++) { - guint32 tmp; - guint16 stmp; - tmp = GUINT16_FROM_BE(*input); - input++; - tmp += GUINT16_FROM_BE(*input); - input++; - stmp = tmp / 2; - *output++ = GUINT16_TO_BE(stmp); - } - return length / 2; -} - -static int -convert_stereo_to_mono_s16le(struct xmms_convert_buffers *buf, - void **data, int length) -{ - gint16 *output = *data, *input = *data; - int i; - for (i = 0; i < length / 4; i++) { - gint32 tmp; - gint16 stmp; - tmp = GINT16_FROM_LE(*input); - input++; - tmp += GINT16_FROM_LE(*input); - input++; - stmp = tmp / 2; - *output++ = GINT16_TO_LE(stmp); - } - return length / 2; -} - -static int -convert_stereo_to_mono_s16be(struct xmms_convert_buffers *buf, - void **data, int length) -{ - gint16 *output = *data, *input = *data; - int i; - for (i = 0; i < length / 4; i++) { - gint32 tmp; - gint16 stmp; - tmp = GINT16_FROM_BE(*input); - input++; - tmp += GINT16_FROM_BE(*input); - input++; - stmp = tmp / 2; - *output++ = GINT16_TO_BE(stmp); - } - return length / 2; -} - -/** - * xmms_convert_get_channel_func: - * @fmt: The format of the data. - * @output: The number of channels to output as. - * @input: The number of channels inbound. - * - * Looks up the proper conversion method to use. - * - * Return value: A function pointer to the desired conversion function. - **/ -convert_channel_func_t -xmms_convert_get_channel_func(AFormat fmt, int output, int input) -{ - fmt = unnativize(fmt); - - if (output == input) - return NULL; - - if (input == 1 && output == 2) - switch (fmt) { - case FMT_U8: - case FMT_S8: - return convert_mono_to_stereo_8; - case FMT_U16_LE: - case FMT_U16_BE: - case FMT_S16_LE: - case FMT_S16_BE: - return convert_mono_to_stereo_16; - default: - g_warning("Unknown format: %d" "No conversion available.", fmt); - return NULL; - } - if (input == 2 && output == 1) - switch (fmt) { - case FMT_U8: - return convert_stereo_to_mono_u8; - case FMT_S8: - return convert_stereo_to_mono_s8; - case FMT_U16_LE: - return convert_stereo_to_mono_u16le; - case FMT_U16_BE: - return convert_stereo_to_mono_u16be; - case FMT_S16_LE: - return convert_stereo_to_mono_s16le; - case FMT_S16_BE: - return convert_stereo_to_mono_s16be; - default: - g_warning("Unknown format: %d. " - "No conversion available.", fmt); - return NULL; - - } - - g_warning("Input has %d channels, soundcard uses %d channels\n" - "No conversion is available", input, output); - return NULL; -} - - -#define RESAMPLE_STEREO(sample_type, bswap) \ - const int shift = sizeof (sample_type); \ - int i, in_samples, out_samples, x, delta; \ - sample_type *inptr = *data, *outptr; \ - guint nlen = (((length >> shift) * ofreq) / ifreq); \ - void *nbuf; \ - if (nlen == 0) \ - return 0; \ - nlen <<= shift; \ - if (bswap) \ - convert_swap_endian(NULL, data, length); \ - nbuf = convert_get_buffer(&buf->freq_buffer, nlen); \ - outptr = nbuf; \ - in_samples = length >> shift; \ - out_samples = nlen >> shift; \ - delta = (in_samples << 12) / out_samples; \ - for (x = 0, i = 0; i < out_samples; i++) \ - { \ - int x1, frac; \ - x1 = (x >> 12) << 12; \ - frac = x - x1; \ - *outptr++ = \ - ((inptr[(x1 >> 12) << 1] * \ - ((1<<12) - frac) + \ - inptr[((x1 >> 12) + 1) << 1] * \ - frac) >> 12); \ - *outptr++ = \ - ((inptr[((x1 >> 12) << 1) + 1] * \ - ((1<<12) - frac) + \ - inptr[(((x1 >> 12) + 1) << 1) + 1] * \ - frac) >> 12); \ - x += delta; \ - } \ - if (bswap) \ - convert_swap_endian(NULL, &nbuf, nlen); \ - *data = nbuf; \ - return nlen; \ - - -#define RESAMPLE_MONO(sample_type, bswap) \ - const int shift = sizeof (sample_type) - 1; \ - int i, x, delta, in_samples, out_samples; \ - sample_type *inptr = *data, *outptr; \ - guint nlen = (((length >> shift) * ofreq) / ifreq); \ - void *nbuf; \ - if (nlen == 0) \ - return 0; \ - nlen <<= shift; \ - if (bswap) \ - convert_swap_endian(NULL, data, length); \ - nbuf = convert_get_buffer(&buf->freq_buffer, nlen); \ - outptr = nbuf; \ - in_samples = length >> shift; \ - out_samples = nlen >> shift; \ - delta = ((length >> shift) << 12) / out_samples; \ - for (x = 0, i = 0; i < out_samples; i++) \ - { \ - int x1, frac; \ - x1 = (x >> 12) << 12; \ - frac = x - x1; \ - *outptr++ = \ - ((inptr[x1 >> 12] * ((1<<12) - frac) + \ - inptr[(x1 >> 12) + 1] * frac) >> 12); \ - x += delta; \ - } \ - if (bswap) \ - convert_swap_endian(NULL, &nbuf, nlen); \ - *data = nbuf; \ - return nlen; \ - -static int -convert_resample_stereo_s16ne(struct xmms_convert_buffers *buf, - void **data, int length, int ifreq, int ofreq) -{ - RESAMPLE_STEREO(gint16, FALSE); -} - -static int -convert_resample_stereo_s16ae(struct xmms_convert_buffers *buf, - void **data, int length, int ifreq, int ofreq) -{ - RESAMPLE_STEREO(gint16, TRUE); -} - -static int -convert_resample_stereo_u16ne(struct xmms_convert_buffers *buf, - void **data, int length, int ifreq, int ofreq) -{ - RESAMPLE_STEREO(guint16, FALSE); -} - -static int -convert_resample_stereo_u16ae(struct xmms_convert_buffers *buf, - void **data, int length, int ifreq, int ofreq) -{ - RESAMPLE_STEREO(guint16, TRUE); -} - -static int -convert_resample_mono_s16ne(struct xmms_convert_buffers *buf, - void **data, int length, int ifreq, int ofreq) -{ - RESAMPLE_MONO(gint16, FALSE); -} - -static int -convert_resample_mono_s16ae(struct xmms_convert_buffers *buf, - void **data, int length, int ifreq, int ofreq) -{ - RESAMPLE_MONO(gint16, TRUE); -} - -static int -convert_resample_mono_u16ne(struct xmms_convert_buffers *buf, - void **data, int length, int ifreq, int ofreq) -{ - RESAMPLE_MONO(guint16, FALSE); -} - -static int -convert_resample_mono_u16ae(struct xmms_convert_buffers *buf, - void **data, int length, int ifreq, int ofreq) -{ - RESAMPLE_MONO(guint16, TRUE); -} - -static int -convert_resample_stereo_u8(struct xmms_convert_buffers *buf, - void **data, int length, int ifreq, int ofreq) -{ - RESAMPLE_STEREO(guint8, FALSE); -} - -static int -convert_resample_mono_u8(struct xmms_convert_buffers *buf, - void **data, int length, int ifreq, int ofreq) -{ - RESAMPLE_MONO(guint8, FALSE); -} - -static int -convert_resample_stereo_s8(struct xmms_convert_buffers *buf, - void **data, int length, int ifreq, int ofreq) -{ - RESAMPLE_STEREO(gint8, FALSE); -} - -static int -convert_resample_mono_s8(struct xmms_convert_buffers *buf, - void **data, int length, int ifreq, int ofreq) -{ - RESAMPLE_MONO(gint8, FALSE); -} - - -/** - * xmms_convert_get_frequency_func: - * @fmt: The format of the data. - * @channels: The number of channels inbound. - * - * Looks up the proper conversion method to use. - * - * Return value: A function pointer to the desired conversion function. - **/ -convert_freq_func_t -xmms_convert_get_frequency_func(AFormat fmt, int channels) -{ - fmt = unnativize(fmt); - g_message("fmt %d, channels: %d", fmt, channels); - - if (channels < 1 || channels > 2) { - g_warning("Unsupported number of channels: %d. " - "Resample function not available", channels); - return NULL; - } - if ((IS_BIG_ENDIAN && fmt == FMT_U16_BE) || - (!IS_BIG_ENDIAN && fmt == FMT_U16_LE)) { - if (channels == 1) - return convert_resample_mono_u16ne; - else - return convert_resample_stereo_u16ne; - } - if ((IS_BIG_ENDIAN && fmt == FMT_S16_BE) || - (!IS_BIG_ENDIAN && fmt == FMT_S16_LE)) { - if (channels == 1) - return convert_resample_mono_s16ne; - else - return convert_resample_stereo_s16ne; - } - if ((!IS_BIG_ENDIAN && fmt == FMT_U16_BE) || - (IS_BIG_ENDIAN && fmt == FMT_U16_LE)) { - if (channels == 1) - return convert_resample_mono_u16ae; - else - return convert_resample_stereo_u16ae; - } - if ((!IS_BIG_ENDIAN && fmt == FMT_S16_BE) || - (IS_BIG_ENDIAN && fmt == FMT_S16_LE)) { - if (channels == 1) - return convert_resample_mono_s16ae; - else - return convert_resample_stereo_s16ae; - } - if (fmt == FMT_U8) { - if (channels == 1) - return convert_resample_mono_u8; - else - return convert_resample_stereo_u8; - } - if (fmt == FMT_S8) { - if (channels == 1) - return convert_resample_mono_s8; - else - return convert_resample_stereo_s8; - } - g_warning("Resample function not available" "Format %d.", fmt); - return NULL; -} diff -r 4e2fc64d95ef -r 3ec22a11c83e src/libaudacious/xconvert.h --- a/src/libaudacious/xconvert.h Sat Jan 27 11:40:05 2007 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2003 Haavard Kvaalen - * - * Licensed under GNU LGPL version 2. - */ - -#include - -struct xmms_convert_buffers; - -struct xmms_convert_buffers *xmms_convert_buffers_new(void); -/* - * Free the data assosiated with the buffers, without destroying the - * context. The context can be reused. - */ -void xmms_convert_buffers_free(struct xmms_convert_buffers *buf); -void xmms_convert_buffers_destroy(struct xmms_convert_buffers *buf); - - -typedef int (*convert_func_t) (struct xmms_convert_buffers * buf, - void **data, int length); -typedef int (*convert_channel_func_t) (struct xmms_convert_buffers * buf, - void **data, int length); -typedef int (*convert_freq_func_t) (struct xmms_convert_buffers * buf, - void **data, int length, int ifreq, - int ofreq); - - -convert_func_t xmms_convert_get_func(AFormat output, AFormat input); -convert_channel_func_t xmms_convert_get_channel_func(AFormat fmt, - int output, - int input); -convert_freq_func_t xmms_convert_get_frequency_func(AFormat fmt, - int channels);