# HG changeset patch # User nenolod # Date 1161852473 25200 # Node ID 59a6cec7e9b10ae619f9946aeded132822d10362 # Parent 96fc1ef32c99872d75c8b90c63532d84eef58ad0 [svn] - a52dec plugin port. *under construction; don't expect to work* diff -r 96fc1ef32c99 -r 59a6cec7e9b1 ChangeLog --- a/ChangeLog Thu Oct 26 00:43:12 2006 -0700 +++ b/ChangeLog Thu Oct 26 01:47:53 2006 -0700 @@ -1,3 +1,11 @@ +2006-10-26 07:43:12 +0000 William Pitcock + revision [244] + - push fixes from p4://depot/svn-audacious-plugins-devel/virt-branches/audalarm/src + + trunk/src/alarm/alarm.c | 7 +------ + 1 file changed, 1 insertion(+), 6 deletions(-) + + 2006-10-26 07:10:28 +0000 William Pitcock revision [242] - add xmms-alarm port diff -r 96fc1ef32c99 -r 59a6cec7e9b1 src/a52dec/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/a52dec/Makefile Thu Oct 26 01:47:53 2006 -0700 @@ -0,0 +1,16 @@ +include ../../mk/rules.mk +include ../../mk/init.mk + +OBJECTIVE_LIBS = liba52dec$(SHARED_SUFFIX) + +LIBDIR = $(plugindir)/$(INPUT_PLUGIN_DIR) + +SOURCES = a52dec.c + +LIBADD = -L/usr/local/lib -la52 + +CFLAGS += $(PICFLAGS) $(GTK_CFLAGS) -I../../intl -I../.. + +OBJECTS = ${SOURCES:.c=.o} + +include ../../mk/objective.mk diff -r 96fc1ef32c99 -r 59a6cec7e9b1 src/a52dec/a52dec.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/a52dec/a52dec.c Thu Oct 26 01:47:53 2006 -0700 @@ -0,0 +1,1535 @@ + +/* + * xmms-a52dec.c + * + * xmms-a52dec 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, or (at your option) + * any later version. + * + * xmms-a52dec 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 GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "a52dec.h" + +#define DRC_BOTH 0 +#define DRC_BOOST 1 +#define DRC_REDUCE 2 + +#define SYNC_SEARCH_LIMIT 65536 +#define COMPRESSION_FACTOR_DEFAULT 0.0 +#define COMPRESSION_TYPE_DEFAULT DRC_BOTH +#define NODOWNMIX_SURROUND_DEFAULT FALSE +#define NODOWNMIX_LFE_DEFAULT FALSE +#define UPMIX_STEREO_DEFAULT FALSE +#define DUALMONO_DEFAULT 1 +#define REQUESTED_OUTPUT_DEFAULT A52_STEREO + +sample_t *sample; +char *buf; +long int lastset_time; +char *name; +int flags, sample_rate, bit_rate, frame_size, length; +FILE *in_file; +int a52_run, a52_not_eof; +gint output_type; // See also: requested_output +int output_nch; + +// Configuration Options. + +gdouble compression_factor; +gboolean compression_type; +gint requested_output; // See also: output_type +gint dualmono_channel; +gboolean nodownmix_surround, nodownmix_lfe, upmix_stereo; + +static pthread_t decode_thread = (pthread_t) NULL; +sem_t play_loop_signal; +pthread_mutex_t infile_lock; + +extern InputPlugin a52_ip; + +static int is_our_file_a52 (char *); +static int synchronise_a52(FILE *, int *, int *, int *, int *); +sample_t dynamic_range(sample_t, void *); +static void init_a52 (void); +static void *play_loop (void *); +void convertsample(sample_t *, int16_t *, int); +int16_t float2int (float); +static void play_a52 (char *); +static void stop_a52 (void); +static int get_time_a52 (void); +static void get_song_info_a52 (char *, char **, int *); +static void pause_a52 (short); +static void seek_a52 (int); +static void about_a52 (void); +static void configure_a52 (void); +static void configure_ok(GtkWidget *, gpointer); +static void configure_apply(GtkWidget *, gpointer); +static void info_a52 (char *); + +InputPlugin a52_ip = { + NULL, + NULL, + "xmms-a52dec 1.0", + init_a52, + about_a52, + configure_a52, + is_our_file_a52, + NULL, + play_a52, + stop_a52, + pause_a52, + seek_a52, + NULL, + get_time_a52, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + get_song_info_a52, + info_a52, + NULL +}; + +InputPlugin * +get_iplugin_info (void) +{ + return &a52_ip; +} + +static void +init_a52 (void) +{ + ConfigDb *config; + + // Retrieve settings from file, setting to default if not found. + + config = bmp_cfg_db_open(); + if (!bmp_cfg_db_get_double(config, "xmms-a52dec", "compression_factor", + &compression_factor)) + { + bmp_cfg_db_set_double(config, "xmms-a52dec", "compression_factor", + COMPRESSION_FACTOR_DEFAULT); + compression_factor = COMPRESSION_FACTOR_DEFAULT; + } + + if (!bmp_cfg_db_get_int(config, "xmms-a52dec", "compression_type", + &compression_type)) + { + bmp_cfg_db_set_int(config, "xmms-a52dec", "compression_type", + COMPRESSION_TYPE_DEFAULT); + compression_type = COMPRESSION_TYPE_DEFAULT; + } + + if (!bmp_cfg_db_get_bool(config, "xmms-a52dec", "nodownmix_surround", + &nodownmix_surround)) + { + bmp_cfg_db_set_bool(config, "xmms-a52dec", "nodownmix_surround", + NODOWNMIX_SURROUND_DEFAULT); + nodownmix_surround = NODOWNMIX_SURROUND_DEFAULT; + } + + if (!bmp_cfg_db_get_bool(config, "xmms-a52dec", "nodownmix_lfe", + &nodownmix_lfe)) + { + bmp_cfg_db_set_bool(config, "xmms-a52dec", "nodownmix_lfe", + NODOWNMIX_LFE_DEFAULT); + nodownmix_lfe = NODOWNMIX_LFE_DEFAULT; + } + + if (!bmp_cfg_db_get_bool(config, "xmms-a52dec", "upmix_stereo", + &upmix_stereo)) + { + bmp_cfg_db_set_bool(config, "xmms-a52dec", "upmix_stereo", + UPMIX_STEREO_DEFAULT); + upmix_stereo = UPMIX_STEREO_DEFAULT; + } + + if (!bmp_cfg_db_get_int(config, "xmms-a52dec", "dualmono_channel", + &dualmono_channel)) + { + bmp_cfg_db_set_int(config, "xmms-a52dec", "dualmono_channel", + DUALMONO_DEFAULT); + requested_output = DUALMONO_DEFAULT; + } + + bmp_cfg_db_close(config); +} + +static int +is_our_file_a52 (char *filename) +{ + int l_flags, l_sample_rate, l_bit_rate, l_frame_size; + gchar *extension; + FILE *temp_file; + + temp_file = fopen (filename, "r"); + if (!temp_file) + return FALSE; + + extension = strrchr (filename, '.'); + + if (extension) + if (!strcasecmp (extension, ".a52") || !strcasecmp (extension, ".ac3")) + if (synchronise_a52(temp_file, &l_flags, &l_sample_rate, + &l_bit_rate, &l_frame_size) == 0) + { + fclose (temp_file); + return TRUE; + } + + fclose (temp_file); + return FALSE; +} + +/* Synchronises a52 bitstream and set parameters. + + Starting from the current file pointer position, search up to + SYNC_SEARCH_LIMIT bytes for a valid frame, and set file pointer + to start of frame. file pointer will be set to an undefined position if + no valid frame found. + + Return 0 if successful. + Return -1 if failed. */ + +static int +synchronise_a52(FILE *file, int *l_flags, int *l_sample_rate, + int *l_bit_rate, int *l_frame_size) +{ + int count; + char temp_buf[7]; + + for (count=0; count <= SYNC_SEARCH_LIMIT; count++) + { + if (fread(temp_buf, 7, 1, file) != 1) + return -1; + + if (fseek(file, -6, SEEK_CUR)) + return -1; + + *l_frame_size = a52_syncinfo (temp_buf, l_flags, l_sample_rate, l_bit_rate); + if (*l_frame_size != 0) + break; + } + + // No valid frame found. + + if (count == SYNC_SEARCH_LIMIT) + return -1; + + // Valid frame found. Go back 1 bytes to return to start of frame. + + if (fseek(file, -1, SEEK_CUR)) + return -1; + + return 0; +} + +sample_t dynamic_range(sample_t recommend, void *nothing) +{ + switch (compression_type) + { + case DRC_BOOST: + if (recommend > 1) + return pow(recommend, (double) compression_factor); + else + return 1; + case DRC_REDUCE: + if (recommend < 1) + return pow(recommend, (double) compression_factor); + else + return 1; + case DRC_BOTH: + default: + return pow(recommend, (double) compression_factor); + } +} + +static void * +play_loop (void *arg) +{ + int old_frame_size, old_bit_rate; + a52_state_t *dec_state; + char *filebuf; + int16_t outbuf[256*6]; + int sample_type; + int first_run=1; + int tempcount; + sample_t level=32766.0; + + /* Re-initialise the a52 library. Without this, there will be + some noise when switching songs */ + + dec_state = a52_init(0); + sample = a52_samples(dec_state); + + a52_run = 1; + lastset_time = 0; + + old_frame_size = frame_size; + old_bit_rate = bit_rate; + filebuf = malloc(frame_size); + + while (a52_run) + { + a52_not_eof = 1; + + /* Lock the mutex before synch and read. + + This prevent a52_seek from calling an fseek between a + synch and read. */ + + pthread_mutex_lock(&infile_lock); + + // Re-synchronise before reading each frame. + + if (synchronise_a52(in_file, &flags, &sample_rate, + &bit_rate, &frame_size) == -1) + { + pthread_mutex_unlock(&infile_lock); + a52_not_eof = 0; + xmms_usleep(1000); + continue; + } + + // Check if frame_size has changed. If yes, realloc filebuf. + + if (frame_size != old_frame_size) + { + filebuf = realloc(filebuf, frame_size); + old_frame_size = frame_size; + } + + if(!fread(filebuf, frame_size, 1, in_file)) + { + pthread_mutex_unlock(&infile_lock); + a52_not_eof = 0; + xmms_usleep(1000); + continue; + } + + pthread_mutex_unlock(&infile_lock); + + if (bit_rate != old_bit_rate) + { + a52_ip.set_info (name, length / (bit_rate / 8 / 1000), + bit_rate, sample_rate, output_nch); + old_bit_rate = bit_rate; + } + + if (nodownmix_surround == TRUE) + sample_type = A52_3F2R | A52_ADJUST_LEVEL; + else + sample_type = output_type | A52_ADJUST_LEVEL; + + if (nodownmix_lfe == TRUE) + sample_type |= A52_LFE; + else + sample_type &= A52_CHANNEL_MASK; + + // The above is for non-5.1, for 5.1 we add in the LFE channel. + + sample_type |= output_type & A52_LFE; + + if(a52_frame(dec_state, filebuf, &sample_type, &level, 0.0)) + break; // Don't know how to deal with this properly. + + a52_dynrng (dec_state, dynamic_range, NULL); + + for (tempcount = 0; tempcount < 6; tempcount++) + { + a52_block(dec_state); + + convertsample(sample, outbuf, sample_type); + + /* Sleep while the buffer is full */ + while (a52_run && (a52_ip.output->buffer_free () < 512 * output_nch)) + xmms_usleep (10000); + + a52_ip.output->write_audio (outbuf, 512 * output_nch); + + /* Signal the play_a52 thread to let it know that we have + finished writing to buffer. It can safely exit now. + + Without this, get_time_a52 may run before we have started + playing anything. get_time_a52 will find that the buffer + is not playing (yet) and return -1 causing stop_a52 to + stop play_loop. + + We must only run this once, because play_a52 will destroy + the semaphore once it receive the signal. */ + + if (first_run) + { + sem_post(&play_loop_signal); + first_run=0; + } + + /* Add visualisation data. Do not use a52_ip.gettime() + for the time. Due to buffering, the time for which the + data is submitted and the current playing time is not + the same. The vis data is sent in advance and must be + set for the correct time. */ + + a52_ip.add_vis_pcm (ftell(in_file) / (bit_rate / 8 / 1000), + FMT_S16_LE, output_nch, 512 * output_nch, outbuf); + } + } + + /* If sem_post didn't run above, we'll run it now */ + + if (first_run) + { + sem_post(&play_loop_signal); + first_run=0; + } + + // Free memory allocated by a52_init. + + a52_free(dec_state); + + /* If we break from the loop due to end of file, the music + is probably still playing, so we'll sleep and wait for + it to end. We'll set a52_not_eof to 0 to let get_time_a52 + know that we have reached the end of file.*/ + + fclose (in_file); + a52_not_eof=0; + + pthread_exit (NULL); +} + +void +convertsample(sample_t *sample, int16_t *outbuf, int sample_type) +{ + int count; + int lfe_offset; + + if (sample_type & A52_LFE) + lfe_offset = 256; + else + lfe_offset = 0; + + for (count = 0; count < 256; count++) + if (output_type == A52_STEREO) + switch (sample_type & A52_CHANNEL_MASK) + { + case A52_MONO: + case A52_CHANNEL1: + case A52_CHANNEL2: + outbuf[count * 2] = float2int (sample[count + lfe_offset]); + outbuf[count * 2 + 1] = outbuf[count * 2]; + break; + case A52_CHANNEL: + if (dualmono_channel == 1) + { + outbuf[count * 2] = float2int (sample[count + lfe_offset]); + outbuf[count * 2 + 1] = outbuf[count * 2]; + } + else + { + outbuf[count * 2] = float2int (sample[count + 256 + lfe_offset]); + outbuf[count * 2 + 1] = outbuf[count * 2]; + } + break; + case A52_STEREO: + case A52_DOLBY: + case A52_2F1R: + case A52_2F2R: + outbuf[count * 2] = float2int (sample[count + lfe_offset]); + outbuf[count * 2 + 1] = float2int (sample[count + 256 + lfe_offset]); + break; + case A52_3F: + case A52_3F1R: + case A52_3F2R: + outbuf[count * 2] = float2int (sample[count + lfe_offset]); + outbuf[count * 2 + 1] = float2int (sample[count + 512 + lfe_offset]); + break; + } + else if (output_type == A52_2F2R) + switch (sample_type & A52_CHANNEL_MASK) + { + case A52_MONO: + case A52_CHANNEL1: + case A52_CHANNEL2: + outbuf[count * 4] = float2int (sample[count + lfe_offset]); + outbuf[count * 4 + 1] = outbuf[count * 4]; + if (upmix_stereo == TRUE) + { + outbuf[count * 4 + 2] = outbuf[count * 4]; + outbuf[count * 4 + 3] = outbuf[count * 4]; + } + else + { + outbuf[count * 4 + 2] = 0; + outbuf[count * 4 + 3] = 0; + } + break; + case A52_CHANNEL: + if (dualmono_channel == 1) + { + outbuf[count * 4] = float2int (sample[count + lfe_offset]); + outbuf[count * 4 + 1] = outbuf[count * 4]; + if (upmix_stereo == TRUE) + { + outbuf[count * 4 + 2] = outbuf[count * 4]; + outbuf[count * 4 + 3] = outbuf[count * 4]; + } + else + { + outbuf[count * 4 + 2] = 0; + outbuf[count * 4 + 3] = 0; + } + } + else + { + outbuf[count * 4] = float2int (sample[count + 256 + lfe_offset]); + outbuf[count * 4 + 1] = outbuf[count * 4]; + if (upmix_stereo == TRUE) + { + outbuf[count * 4 + 2] = outbuf[count * 4]; + outbuf[count * 4 + 3] = outbuf[count * 4]; + } + else + { + outbuf[count * 4 + 2] = 0; + outbuf[count * 4 + 3] = 0; + } + } + break; + case A52_STEREO: + case A52_DOLBY: + outbuf[count * 4] = float2int (sample[count + lfe_offset]); + outbuf[count * 4 + 1] = float2int (sample[count + 256 + lfe_offset]); + if (upmix_stereo == TRUE) + { + outbuf[count * 4 + 2] = outbuf[count * 4]; + outbuf[count * 4 + 3] = outbuf[count * 4 + 1]; + } + else + { + outbuf[count * 4 + 2] = 0; + outbuf[count * 4 + 3] = 0; + } + break; + case A52_3F: + outbuf[count * 4] = float2int (sample[count + lfe_offset]); + outbuf[count * 4 + 1] = float2int (sample[count + 512 + lfe_offset]); + if (upmix_stereo == TRUE) + { + outbuf[count * 4 + 2] = outbuf[count * 4]; + outbuf[count * 4 + 3] = outbuf[count * 4 + 1]; + } + else + { + outbuf[count * 4 + 2] = 0; + outbuf[count * 4 + 3] = 0; + } + break; + case A52_2F1R: + outbuf[count * 4] = float2int (sample[count + lfe_offset]); + outbuf[count * 4 + 1] = float2int (sample[count + 256 + lfe_offset]); + outbuf[count * 4 + 2] = float2int (sample[count + 512 + lfe_offset]); + outbuf[count * 4 + 3] = outbuf[count * 4 + 2]; + break; + case A52_2F2R: + outbuf[count * 4] = float2int (sample[count + lfe_offset]); + outbuf[count * 4 + 1] = float2int (sample[count + 256 + lfe_offset]); + outbuf[count * 4 + 2] = float2int (sample[count + 512 + lfe_offset]); + outbuf[count * 4 + 3] = float2int (sample[count + 768 + lfe_offset]); + break; + case A52_3F1R: + outbuf[count * 4] = float2int (sample[count + lfe_offset]); + outbuf[count * 4 + 1] = float2int (sample[count + 512 + lfe_offset]); + outbuf[count * 4 + 2] = float2int (sample[count + 768 + lfe_offset]); + outbuf[count * 4 + 3] = outbuf[count * 4 + 2]; + break; + case A52_3F2R: + outbuf[count * 4] = float2int (sample[count + lfe_offset]); + outbuf[count * 4 + 1] = float2int (sample[count + 512 + lfe_offset]); + outbuf[count * 4 + 2] = float2int (sample[count + 768 + lfe_offset]); + outbuf[count * 4 + 3] = float2int (sample[count + 1024 + lfe_offset]); + break; + } + else if (output_type == A52_3F2R) + switch (sample_type & A52_CHANNEL_MASK) + { + case A52_MONO: + case A52_CHANNEL1: + case A52_CHANNEL2: + outbuf[count * 5] = float2int (sample[count + lfe_offset]); + outbuf[count * 5 + 1] = outbuf[count * 5]; + if (upmix_stereo == TRUE) + { + outbuf[count * 5 + 2] = outbuf[count * 5]; + outbuf[count * 5 + 3] = outbuf[count * 5]; + } + else + { + outbuf[count * 5 + 2] = 0; + outbuf[count * 5 + 3] = 0; + } + outbuf[count * 5 + 4] = outbuf[count * 5]; + break; + case A52_CHANNEL: + if (dualmono_channel == 1) + { + outbuf[count * 5] = float2int (sample[count + lfe_offset]); + outbuf[count * 5 + 1] = outbuf[count * 5]; + if (upmix_stereo == TRUE) + { + outbuf[count * 5 + 2] = outbuf[count * 5]; + outbuf[count * 5 + 3] = outbuf[count * 5]; + } + else + { + outbuf[count * 5 + 2] = 0; + outbuf[count * 5 + 3] = 0; + } + } + else + { + outbuf[count * 5] = float2int (sample[count + 256 + lfe_offset]); + outbuf[count * 5 + 1] = outbuf[count * 5]; + if (upmix_stereo == TRUE) + { + outbuf[count * 5 + 2] = outbuf[count * 5]; + outbuf[count * 5 + 3] = outbuf[count * 5]; + } + else + { + outbuf[count * 5 + 2] = 0; + outbuf[count * 5 + 3] = 0; + } + } + break; + case A52_STEREO: + case A52_DOLBY: + outbuf[count * 5] = float2int (sample[count + lfe_offset]); + outbuf[count * 5 + 1] = float2int (sample[count + 256 + lfe_offset]); + if (upmix_stereo == TRUE) + { + outbuf[count * 5 + 2] = outbuf[count * 5]; + outbuf[count * 5 + 3] = outbuf[count * 5 + 1]; + } + else + { + outbuf[count * 5 + 2] = 0; + outbuf[count * 5 + 3] = 0; + } + outbuf[count * 5 + 4] = 0; + break; + case A52_3F: + outbuf[count * 5] = float2int (sample[count + lfe_offset]); + outbuf[count * 5 + 1] = float2int (sample[count + 512 + lfe_offset]); + if (upmix_stereo == TRUE) + { + outbuf[count * 5 + 2] = outbuf[count * 5]; + outbuf[count * 5 + 3] = outbuf[count * 5 + 1]; + } + else + { + outbuf[count * 5 + 2] = 0; + outbuf[count * 5 + 3] = 0; + } + outbuf[count * 5 + 4] = float2int (sample[count + 256 + lfe_offset]); + break; + case A52_2F1R: + outbuf[count * 5] = float2int (sample[count + lfe_offset]); + outbuf[count * 5 + 1] = float2int (sample[count + 256 + lfe_offset]); + outbuf[count * 5 + 2] = float2int (sample[count + 512 + lfe_offset]); + outbuf[count * 5 + 3] = outbuf[count * 5 + 2]; + outbuf[count * 5 + 4] = 0; + break; + case A52_2F2R: + outbuf[count * 5] = float2int (sample[count + lfe_offset]); + outbuf[count * 5 + 1] = float2int (sample[count + 256 + lfe_offset]); + outbuf[count * 5 + 2] = float2int (sample[count + 512 + lfe_offset]); + outbuf[count * 5 + 3] = float2int (sample[count + 768 + lfe_offset]); + outbuf[count * 5 + 4] = 0; + break; + case A52_3F1R: + outbuf[count * 5] = float2int (sample[count + lfe_offset]); + outbuf[count * 5 + 1] = float2int (sample[count + 512 + lfe_offset]); + outbuf[count * 5 + 2] = float2int (sample[count + 768 + lfe_offset]); + outbuf[count * 5 + 3] = outbuf[count * 5 + 2]; + outbuf[count * 5 + 4] = float2int (sample[count + 256 + lfe_offset]); + break; + case A52_3F2R: + outbuf[count * 5] = float2int (sample[count + lfe_offset]); + outbuf[count * 5 + 1] = float2int (sample[count + 512 + lfe_offset]); + outbuf[count * 5 + 2] = float2int (sample[count + 768 + lfe_offset]); + outbuf[count * 5 + 3] = float2int (sample[count + 1024 + lfe_offset]); + outbuf[count * 5 + 4] = float2int (sample[count + 256 + lfe_offset]); + break; + } + else if (output_type == (A52_3F2R | A52_LFE)) + switch (sample_type & A52_CHANNEL_MASK) + { + case A52_MONO: + case A52_CHANNEL1: + case A52_CHANNEL2: + outbuf[count * 6] = float2int (sample[count + lfe_offset]); + outbuf[count * 6 + 1] = outbuf[count * 6]; + if (upmix_stereo == TRUE) + { + outbuf[count * 6 + 2] = outbuf[count * 6]; + outbuf[count * 6 + 3] = outbuf[count * 6]; + } + else + { + outbuf[count * 6 + 2] = 0; + outbuf[count * 6 + 3] = 0; + } + outbuf[count * 6 + 4] = outbuf[count * 6]; + if (lfe_offset) + outbuf[count * 6 + 5] = float2int (sample[count]); + else + outbuf[count * 6 + 5] = 0; + break; + case A52_CHANNEL: + if (dualmono_channel == 1) + { + outbuf[count * 6] = float2int (sample[count + lfe_offset]); + outbuf[count * 6 + 1] = outbuf[count * 6]; + if (upmix_stereo == TRUE) + { + outbuf[count * 6 + 2] = outbuf[count * 6]; + outbuf[count * 6 + 3] = outbuf[count * 6]; + } + else + { + outbuf[count * 6 + 2] = 0; + outbuf[count * 6 + 3] = 0; + } + } + else + { + outbuf[count * 6] = float2int (sample[count + 256 + lfe_offset]); + outbuf[count * 6 + 1] = outbuf[count * 6]; + if (upmix_stereo == TRUE) + { + outbuf[count * 6 + 2] = outbuf[count * 6]; + outbuf[count * 6 + 3] = outbuf[count * 6]; + } + else + { + outbuf[count * 6 + 2] = 0; + outbuf[count * 6 + 3] = 0; + } + } + break; + case A52_STEREO: + case A52_DOLBY: + outbuf[count * 6] = float2int (sample[count + lfe_offset]); + outbuf[count * 6 + 1] = float2int (sample[count + 256 + lfe_offset]); + if (upmix_stereo == TRUE) + { + outbuf[count * 6 + 2] = outbuf[count * 6]; + outbuf[count * 6 + 3] = outbuf[count * 6 + 1]; + } + else + { + outbuf[count * 6 + 2] = 0; + outbuf[count * 6 + 3] = 0; + } + outbuf[count * 6 + 4] = 0; + if (lfe_offset) + outbuf[count * 6 + 5] = float2int (sample[count]); + else + outbuf[count * 6 + 5] = 0; + break; + case A52_3F: + outbuf[count * 6] = float2int (sample[count + lfe_offset]); + outbuf[count * 6 + 1] = float2int (sample[count + 512 + lfe_offset]); + if (upmix_stereo == TRUE) + { + outbuf[count * 6 + 2] = outbuf[count * 6]; + outbuf[count * 6 + 3] = outbuf[count * 6 + 1]; + } + else + { + outbuf[count * 6 + 2] = 0; + outbuf[count * 6 + 3] = 0; + } + outbuf[count * 6 + 4] = float2int (sample[count + 256 + lfe_offset]); + if (lfe_offset) + outbuf[count * 6 + 5] = float2int (sample[count]); + else + outbuf[count * 6 + 5] = 0; + break; + case A52_2F1R: + outbuf[count * 6] = float2int (sample[count + lfe_offset]); + outbuf[count * 6 + 1] = float2int (sample[count + 256 + lfe_offset]); + outbuf[count * 6 + 2] = float2int (sample[count + 512 + lfe_offset]); + outbuf[count * 6 + 3] = outbuf[count * 6 + 2]; + outbuf[count * 6 + 4] = 0; + if (lfe_offset) + outbuf[count * 6 + 5] = float2int (sample[count]); + else + outbuf[count * 6 + 5] = 0; + break; + case A52_2F2R: + outbuf[count * 6] = float2int (sample[count + lfe_offset]); + outbuf[count * 6 + 1] = float2int (sample[count + 256 + lfe_offset]); + outbuf[count * 6 + 2] = float2int (sample[count + 512 + lfe_offset]); + outbuf[count * 6 + 3] = float2int (sample[count + 768 + lfe_offset]); + outbuf[count * 6 + 4] = 0; + if (lfe_offset) + outbuf[count * 6 + 5] = float2int (sample[count]); + else + outbuf[count * 6 + 5] = 0; + break; + case A52_3F1R: + outbuf[count * 6] = float2int (sample[count + lfe_offset]); + outbuf[count * 6 + 1] = float2int (sample[count + 512 + lfe_offset]); + outbuf[count * 6 + 2] = float2int (sample[count + 768 + lfe_offset]); + outbuf[count * 6 + 3] = outbuf[count * 6 + 2]; + outbuf[count * 6 + 4] = float2int (sample[count + 256 + lfe_offset]); + if (lfe_offset) + outbuf[count * 6 + 5] = float2int (sample[count]); + else + outbuf[count * 6 + 5] = 0; + break; + case A52_3F2R: + outbuf[count * 6] = float2int (sample[count + lfe_offset]); + outbuf[count * 6 + 1] = float2int (sample[count + 512 + lfe_offset]); + outbuf[count * 6 + 2] = float2int (sample[count + 768 + lfe_offset]); + outbuf[count * 6 + 3] = float2int (sample[count + 1024 + lfe_offset]); + outbuf[count * 6 + 4] = float2int (sample[count + 256 + lfe_offset]); + if (lfe_offset) + outbuf[count * 6 + 5] = float2int (sample[count]); + else + outbuf[count * 6 + 5] = 0; + break; + } + else if (output_type == A52_DOLBY) + switch (sample_type & A52_CHANNEL_MASK) + { + case A52_CHANNEL1: + case A52_CHANNEL2: + outbuf[count * 2] = float2int (sample[count + lfe_offset]); + outbuf[count * 2 + 1] = outbuf[count * 2]; + break; + case A52_CHANNEL: + if (dualmono_channel == 1) + { + outbuf[count * 2] = float2int (sample[count + lfe_offset]); + outbuf[count * 2 + 1] = outbuf[count * 2]; + } + else + { + outbuf[count * 2] = float2int (sample[count + 256 + lfe_offset]); + outbuf[count * 2 + 1] = outbuf[count * 2]; + } + break; + case A52_STEREO: + case A52_DOLBY: + outbuf[count * 2] = float2int (sample[count + lfe_offset]); + outbuf[count * 2 + 1] = float2int (sample[count + 256 + lfe_offset]); + break; + } +} + +int16_t +float2int (float sample) +{ + if (sample > 32767.0) + return 32767; + else if (sample < -32767.0) + return -32767; + else + return (int16_t) sample; +} + +static void +play_a52 (char *filename) +{ + char *temp; + + if (a52_run) + return; + + in_file = fopen (filename, "r"); + + if (!in_file) + return; + + if (synchronise_a52(in_file, &flags, &sample_rate, + &bit_rate, &frame_size) == -1) + { + fclose(in_file); + return; + } + + output_type = requested_output; + + if ((output_type & A52_STEREO) || (output_type & A52_DOLBY)) + { + output_nch = a52_ip.output->open_audio (FMT_S16_NE, sample_rate, 2); + if (output_nch == 0) + { + fclose (in_file); + return; + } + } + + if (output_type != A52_DOLBY) + output_type = A52_STEREO; + + /* don't ask. -nenolod */ + if (output_nch == 1) + output_nch = 2; + + // Get song title + + temp = strrchr (filename, '/'); + if (!temp) + temp = filename; + else + temp++; + name = malloc (strlen (temp) + 1); + strcpy (name, temp); + *strrchr (name, '.') = '\0'; + + // Get song length + + fseek (in_file, 0, SEEK_END); + + /* If we can get the file length, we divide it by byterate (not bitrate) + and multiply by 1000 to get time in milliseconds. + If we can't get file length, we'll set it to -1 + + length (the variable) : file length + length (passed to set_info) : milliseconds + bit_rate : bits/second + sample_rate : sample/second */ + + if ((length = ftell (in_file)) != -1) + a52_ip.set_info (name, length / (bit_rate / 8 / 1000), + bit_rate, sample_rate, 2); + else + a52_ip.set_info (name, -1, bit_rate, sample_rate, 2); + + free(name); + + // Return to start of file. + + fseek (in_file, 0, SEEK_SET); + + // Mutex will be used in play_loop. + + pthread_mutex_destroy(&infile_lock); + pthread_mutex_init(&infile_lock, NULL); + + /* Ensure that play_loop has written to the buffer before exiting. + See play_loop for further details. */ + + sem_init(&play_loop_signal, 0, 0); + pthread_create (&decode_thread, NULL, play_loop, NULL); + sem_wait(&play_loop_signal); + sem_destroy(&play_loop_signal); + + return; +} + +static void +stop_a52 (void) +{ + if (a52_run) + { + a52_run = 0; + pthread_join (decode_thread, NULL); + a52_ip.output->close_audio (); + } +} + +static int +get_time_a52 (void) +{ + /* lastset_time is set when playing starts and + when seeking. We can't use it directly because + it's based on file position for reading. Due to + buffering, the file position is always ahead of + the play position. + + Instead, we set lastset_time when playing and + seeking, and use the output_time() as an offset. */ + + a52_ip.output->buffer_free(); + + if ((a52_run && a52_not_eof) || a52_ip.output->buffer_playing ()) + return lastset_time + a52_ip.output->output_time (); + + return -1; +} + +static void +pause_a52 (short paused) +{ + a52_ip.output->pause (paused); +} + +static void +get_song_info_a52 (gchar * filename, gchar ** title, gint * info_length) +{ + int l_flags, l_sample_rate, l_bit_rate, l_frame_size; + FILE *temp_file; + char *temp_name, *temp; + + // Set the song title + + temp = strrchr (filename, '/'); + if (!temp) + temp = filename; + else + temp++; + temp_name = malloc (strlen (temp) + 1); + strcpy (temp_name, temp); + *strrchr (temp_name, '.') = '\0'; + (*title) = temp_name; + + // Determine the song length from filesize. + + temp_file = fopen (filename, "r"); + + if (synchronise_a52(temp_file, &l_flags, &l_sample_rate, + &l_bit_rate, &l_frame_size) == -1) + { + *info_length = -1; + return; + } + + fseek (temp_file, 0, SEEK_END); + + if ((*info_length = ftell (temp_file)) == -1) + { + // Can't get file position + *info_length = -1; + return; + } + + // Song length in milliseconds + + *info_length = *info_length / (l_bit_rate / 8 / 1000); +} + +static void +seek_a52 (gint time) +{ + // time is in seconds. + + // Don't seek while play_loop is reading/synching. + + pthread_mutex_lock(&infile_lock); + fseek(in_file, time * bit_rate / 8, SEEK_SET); + pthread_mutex_unlock(&infile_lock); + + a52_ip.output->flush (0); + lastset_time = time * 1000; +} + +void +about_a52 (void) +{ + GdkPixmap *pixmap; + GdkBitmap *mask; + GtkStyle *style; + static GtkWidget *dialog, *button, *label, *pixmapwid; + + if (dialog) + return; + + dialog = gtk_dialog_new (); + gtk_signal_connect (GTK_OBJECT (dialog), "destroy", + GTK_SIGNAL_FUNC (gtk_widget_destroyed), &dialog); + gtk_window_set_title (GTK_WINDOW (dialog), "About xmms-a52dec 1.0"); + gtk_window_set_policy (GTK_WINDOW (dialog), FALSE, FALSE, FALSE); + gtk_container_border_width (GTK_CONTAINER (dialog), 5); + label = gtk_label_new ("\nXMMS-AC3DEC VERSION 1.0\n\n \ +An A52/AC3 decoder plugin for xmms based on the a52dec package.\n \ +\nCoded by Cort \nEnhanced by David Weisgerber "); + + /* now for the pixmap from gdk */ + style = gtk_widget_get_style (dialog); + pixmap = gdk_pixmap_create_from_xpm_d (dialog->window, &mask, + &style->bg[GTK_STATE_NORMAL], + (gchar **) a52dec_xpm); + /* a pixmap widget to contain the pixmap */ + pixmapwid = gtk_pixmap_new (pixmap, NULL); + gtk_widget_show (pixmapwid); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), pixmapwid, TRUE, + TRUE, 0); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), label, TRUE, TRUE, + 0); + gtk_widget_show (label); + + button = gtk_button_new_with_label (" Close "); + gtk_signal_connect_object (GTK_OBJECT (button), "clicked", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + GTK_OBJECT (dialog)); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), button, + FALSE, FALSE, 0); + + gtk_widget_show (button); + gtk_widget_show (dialog); + gtk_widget_grab_focus (button); +} + +static GtkWidget *drc_scale, *drc_both, *drc_boost, *drc_reduce; +static GtkWidget *effect_surround, *effect_lfe, *effect_upmix; +static GtkWidget *dualmono_channel1, *dualmono_channel2; + +void +configure_a52 (void) +{ + static GtkWidget *dialog; + static GtkWidget *button_cancel, *button_apply, *button_ok; + static GtkWidget *hbox, *vbox, *vbox2; + static GtkWidget *effect_vbox, *button_hbox, *dualmono_vbox; + static GtkWidget *drc_vbox; + static GtkWidget *range_frame, *effect_frame, *output_frame, *dualmono_frame; + static GtkTooltips *tooltips; + + if (dialog) + return; + + tooltips = gtk_tooltips_new(); + + // Create dialog and set window parameters. + + dialog = gtk_dialog_new (); + gtk_signal_connect (GTK_OBJECT (dialog), "destroy", + GTK_SIGNAL_FUNC (gtk_widget_destroyed), &dialog); + gtk_window_set_title (GTK_WINDOW (dialog), "xmms-a52dec Configuration"); + gtk_window_set_policy (GTK_WINDOW (dialog), FALSE, FALSE, FALSE); + gtk_container_border_width (GTK_CONTAINER (dialog), 5); + + // Prepare all the vbox and hbox. + + hbox = gtk_hbox_new(FALSE, 5); + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, TRUE, TRUE, + 0); + vbox = gtk_vbox_new(FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0); + vbox2 = gtk_vbox_new(FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), vbox2, TRUE, TRUE, 0); + + // Prepare all the frames. + + range_frame = gtk_frame_new("Dynamic Range Compression"); + effect_frame = gtk_frame_new("Effect"); + output_frame = gtk_frame_new("Output"); + dualmono_frame = gtk_frame_new("Dual Mono"); + + // Pack the frames in. + + gtk_box_pack_start (GTK_BOX (vbox), range_frame, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox), effect_frame, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox2), output_frame, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (vbox2), dualmono_frame, TRUE, TRUE, 0); + + // Create Dynamic Range Compression options. + + drc_vbox = gtk_vbox_new(FALSE, 0); + drc_scale = gtk_hscale_new (GTK_ADJUSTMENT + (gtk_adjustment_new + (compression_factor, 0, 1, 0.01, 0.1, 0))); + gtk_scale_set_digits (GTK_SCALE (drc_scale), 2); + drc_both = gtk_radio_button_new_with_label (NULL, "Boost and Reduce"); + drc_boost = gtk_radio_button_new_with_label_from_widget ( + GTK_RADIO_BUTTON(drc_both), "Boost only"); + drc_reduce = gtk_radio_button_new_with_label_from_widget ( + GTK_RADIO_BUTTON(drc_both), "Reduce only"); + gtk_box_pack_start (GTK_BOX (drc_vbox), drc_scale, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (drc_vbox), drc_both, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (drc_vbox), drc_boost, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (drc_vbox), drc_reduce, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER(range_frame), drc_vbox); + + if (compression_type == DRC_BOTH) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(drc_both), TRUE); + else if (compression_type == DRC_BOOST) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(drc_boost), TRUE); + else if (compression_type == DRC_REDUCE) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(drc_reduce), TRUE); + + + // Create effect toggle button. + + effect_vbox = gtk_vbox_new(FALSE, 0); + effect_surround = gtk_check_button_new_with_label("No downmix of surround"); + effect_lfe = gtk_check_button_new_with_label("No downmix of LFE channel"); + effect_upmix = gtk_check_button_new_with_label("Upmix stereo to surround"); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(effect_surround), + nodownmix_surround); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(effect_lfe), nodownmix_lfe); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(effect_upmix), upmix_stereo); + gtk_box_pack_start (GTK_BOX (effect_vbox), effect_surround, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (effect_vbox), effect_lfe, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (effect_vbox), effect_upmix, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER(effect_frame), effect_vbox); + + // Create dualmono channel radio button. + + dualmono_vbox = gtk_vbox_new(FALSE, 0); + dualmono_channel1 = gtk_radio_button_new_with_label (NULL, "Play First channel"); + dualmono_channel2 = gtk_radio_button_new_with_label_from_widget ( + GTK_RADIO_BUTTON(dualmono_channel1), "Play Second channel"); + + if (dualmono_channel == 1) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dualmono_channel1), TRUE); + else + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(dualmono_channel2), TRUE); + + gtk_box_pack_start (GTK_BOX (dualmono_vbox), dualmono_channel1, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (dualmono_vbox), dualmono_channel2, TRUE, TRUE, 0); + gtk_container_add (GTK_CONTAINER(dualmono_frame), dualmono_vbox); + + // Create hbuttonbox for buttons. + + button_hbox = gtk_hbutton_box_new(); + + // Create cancel button. + + button_cancel = gtk_button_new_with_label ("Cancel"); + gtk_signal_connect_object (GTK_OBJECT (button_cancel), "clicked", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + GTK_OBJECT (dialog)); + gtk_box_pack_start(GTK_BOX(button_hbox), button_cancel, TRUE, TRUE, 0); + + // Create apply button. + + button_apply = gtk_button_new_with_label ("Apply"); + gtk_signal_connect_object (GTK_OBJECT (button_apply), "clicked", + GTK_SIGNAL_FUNC (configure_apply), + GTK_OBJECT (dialog)); + gtk_box_pack_start(GTK_BOX(button_hbox), button_apply, TRUE, TRUE, 0); + + // Create ok button. + + button_ok = gtk_button_new_with_label ("Ok"); + gtk_signal_connect_object (GTK_OBJECT (button_ok), "clicked", + GTK_SIGNAL_FUNC (configure_ok), + GTK_OBJECT (dialog)); + gtk_box_pack_start(GTK_BOX(button_hbox), button_ok, TRUE, TRUE, 0); + + // Pack hbuttonbox into dialog. + + gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area), + button_hbox, TRUE, TRUE,0); + + // Set tooltips. + + gtk_tooltips_set_tip(GTK_TOOLTIPS (tooltips), drc_scale, + "Dynamic range compression is used to lower the\ + volume of loud sounds and increase the volume of\ + soft sounds.\nSet to 0.00 if you wish to disable this feature.", NULL); + + gtk_tooltips_set_tip(GTK_TOOLTIPS (tooltips), drc_both, + "Boost the volume of soft sounds and reduce the volume\ + of loud sounds.", NULL); + + gtk_tooltips_set_tip(GTK_TOOLTIPS (tooltips), drc_boost, + "Boost the volume of soft sounds, but leave loud sounds\ + unchanged.", NULL); + + gtk_tooltips_set_tip(GTK_TOOLTIPS (tooltips), drc_reduce, + "Reduce the volume of loud sounds, but leave soft sounds\ + unchanged.", NULL); + + gtk_tooltips_set_tip(GTK_TOOLTIPS (tooltips), dualmono_channel1, + "Dualmono tracks contain 2 seperate mono channels. Select\ + this option to play the first channels.", NULL); + + gtk_tooltips_set_tip(GTK_TOOLTIPS (tooltips), dualmono_channel2, + "Dualmono tracks contain 2 seperate mono channels. Select\ + this option to play the second channels.", NULL); + + // Show all of the above. + + gtk_widget_show (hbox); + gtk_widget_show (vbox); + gtk_widget_show (vbox2); + gtk_widget_show (range_frame); + gtk_widget_show (drc_scale); + gtk_widget_show (drc_both); + gtk_widget_show (drc_boost); + gtk_widget_show (drc_reduce); + gtk_widget_show (drc_vbox); + gtk_widget_show (effect_frame); + gtk_widget_show (effect_surround); + gtk_widget_show (effect_lfe); + gtk_widget_show (effect_upmix); + gtk_widget_show (effect_vbox); + gtk_widget_show (dualmono_vbox); + gtk_widget_show (dualmono_channel1); + gtk_widget_show (dualmono_channel2); + gtk_widget_show (dualmono_frame); + gtk_widget_show (button_hbox); + gtk_widget_show (button_cancel); + gtk_widget_show (button_apply); + gtk_widget_show (button_ok); + gtk_widget_show (dialog); + gtk_widget_grab_focus (button_ok); +} + +static void configure_ok(GtkWidget * w, gpointer data) +{ + // Let configure_apply set and save compression_factor. + + configure_apply(NULL, NULL); + + // Close the window. + + gtk_widget_destroy(w); +} + +static void configure_apply(GtkWidget * w, gpointer data) +{ + GtkAdjustment *scale_adj; + ConfigDb *config; + + scale_adj = gtk_range_get_adjustment(GTK_RANGE(drc_scale)); + compression_factor = (gdouble) scale_adj->value; + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(drc_both)) == TRUE) + compression_type = DRC_BOTH; + else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(drc_boost)) == TRUE) + compression_type = DRC_BOOST; + else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(drc_reduce)) == TRUE) + compression_type = DRC_REDUCE; + + nodownmix_surround = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(effect_surround)); + nodownmix_lfe = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(effect_lfe)); + upmix_stereo = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(effect_upmix)); + requested_output = A52_STEREO; + + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(dualmono_channel1)) == TRUE) + dualmono_channel = 1; + else + dualmono_channel = 2; + + config = bmp_cfg_db_open(); + bmp_cfg_db_set_double(config, "xmms-a52dec", "compression_factor", + compression_factor); + bmp_cfg_db_set_int(config, "xmms-a52dec", "compression_type", + compression_type); + bmp_cfg_db_set_bool(config, "xmms-a52dec", "nodownmix_surround", + nodownmix_surround); + bmp_cfg_db_set_bool(config, "xmms-a52dec", "nodownmix_lfe", + nodownmix_lfe); + bmp_cfg_db_set_bool(config, "xmms-a52dec", "upmix_stereo", + upmix_stereo); + bmp_cfg_db_set_int(config, "xmms-a52dec", "requested_output", + requested_output); + bmp_cfg_db_close(config); +} + +void +info_a52 (char *filename) +{ + static GtkWidget *window; + static GtkWidget *button_ok; + static GtkWidget *hbox, *vbox, *label, *label2, *entry, *frame; + static char *temp_text, *label2_text, *temp, *temp_name; + FILE *temp_file; + int l_flags, l_sample_rate, l_bit_rate, l_frame_size, l_length; + int no_window = 0; + + if (!window) + no_window = 1; + + // Create window and set parameters. + + if (no_window) + { + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_signal_connect (GTK_OBJECT (window), "destroy", + GTK_SIGNAL_FUNC (gtk_widget_destroyed), &window); + gtk_window_set_default_size (GTK_WINDOW (window), 485, -1); + gtk_window_set_policy (GTK_WINDOW (window), FALSE, FALSE, TRUE); + gtk_container_border_width (GTK_CONTAINER (window), 5); + } + + temp = strrchr (filename, '/'); + if (!temp) + temp = filename; + else + temp++; + temp_name = malloc (strlen (temp) + 1); + strcpy (temp_name, temp); + *strrchr (temp_name, '.') = '\0'; + + sprintf(temp_text, "File Info - %s", temp_name); + gtk_window_set_title (GTK_WINDOW (window), temp_text); + + free(temp_name); + free(temp_text); + + // Create vbuttonbox for filename and fileinfo frame. + + if (no_window) + { + vbox = gtk_vbox_new(FALSE, 0); + + // Create label with a text entry containing filename. + + hbox = gtk_hbox_new(FALSE, 0); + gtk_box_pack_start(GTK_BOX(vbox), hbox, TRUE, TRUE, 8); + label = gtk_label_new ("Filename: "); + gtk_label_set_justify (GTK_LABEL(label), GTK_JUSTIFY_LEFT); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + entry = gtk_entry_new (); + gtk_widget_set_usize (entry, 400, -1); + gtk_editable_set_editable(GTK_EDITABLE(entry), FALSE); + gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); + } + gtk_entry_set_text (GTK_ENTRY(entry), filename); + + // Determine the song length from filesize. + + temp_file = fopen (filename, "r"); + + if (synchronise_a52(temp_file, &l_flags, &l_sample_rate, + &l_bit_rate, &l_frame_size) == -1) + { + l_length = -1; + return; + } + + fseek (temp_file, 0, SEEK_END); + + if ((l_length = ftell (temp_file)) == -1) + { + // Can't get file position + l_length = -1; + return; + } + + // Determine channel type. + + switch (l_flags & A52_CHANNEL_MASK) + { + case A52_CHANNEL: + sprintf(temp_text, "Channel"); + break; + case A52_MONO: + sprintf(temp_text, "Mono"); + break; + case A52_STEREO: + sprintf(temp_text, "Stereo"); + break; + case A52_3F: + sprintf(temp_text, "3 Front"); + break; + case A52_2F1R: + sprintf(temp_text, "2 Front 1 Rear"); + break; + case A52_3F1R: + sprintf(temp_text, "3 Front 1 Rear"); + break; + case A52_2F2R: + sprintf(temp_text, "2 Front 2 Rear"); + break; + case A52_3F2R: + sprintf(temp_text, "3 Front 2 Rear"); + break; + case A52_CHANNEL1: + sprintf(temp_text, "Channel1"); + break; + case A52_CHANNEL2: + sprintf(temp_text, "Channel2"); + break; + case A52_DOLBY: + sprintf(temp_text, "Dolby"); + break; + } + + // Create frame for file info. + + if (no_window) + { + frame = gtk_frame_new ("A/52 Info:"); + gtk_box_pack_start(GTK_BOX(vbox), frame, TRUE, TRUE, 8); + + // Create label inside frame. + + label2 = gtk_label_new (NULL); + gtk_container_add(GTK_CONTAINER(frame), label2); + gtk_misc_set_alignment (GTK_MISC (label2), 0, 0); + gtk_label_set_justify (GTK_LABEL(label2), GTK_JUSTIFY_LEFT); + + } + + // Set text of label inside frame. + + if (l_flags & A52_LFE) + sprintf(label2_text, "\n Bitrate: %d kb/s\n Samplerate: %d Hz\n Channel Type: %s\n Low Frequency Enhancement: Yes\n %d frames\n Filesize: %d B\n", + l_bit_rate / 1000, l_sample_rate, temp_text, l_length / l_frame_size, l_length); + else + sprintf(label2_text, "\n Bitrate: %d kb/s\n Samplerate: %d Hz\n Channel Type: %s\n Low Frequency Enhancement: No\n %d frames\n Filesize: %d B\n", + l_bit_rate / 1000, l_sample_rate, temp_text, l_length / l_frame_size, l_length); + + gtk_label_set_text (GTK_LABEL(label2), label2_text); + + if (no_window) + { + // Create ok button. + + button_ok = gtk_button_new_with_label ("Ok"); + gtk_signal_connect_object (GTK_OBJECT (button_ok), "clicked", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + GTK_OBJECT (window)); + gtk_widget_set_usize (button_ok, 100, -1); + gtk_box_pack_start(GTK_BOX (vbox), button_ok, + TRUE, FALSE, 8); + + // Pack vbuttonbox into window. + + gtk_container_add (GTK_CONTAINER (window), vbox); + + // Show all of the above. + + gtk_widget_show (label2); + gtk_widget_show (label); + gtk_widget_show (entry); + gtk_widget_show (frame); + gtk_widget_show (hbox); + gtk_widget_show (button_ok); + gtk_widget_show (vbox); + gtk_widget_show (window); + gtk_widget_grab_focus (button_ok); + } +} diff -r 96fc1ef32c99 -r 59a6cec7e9b1 src/a52dec/a52dec.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/a52dec/a52dec.h Thu Oct 26 01:47:53 2006 -0700 @@ -0,0 +1,157 @@ +/* + * xmms-a52dec.h + * + * xmms-a52dec 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, or (at your option) + * any later version. + * + * xmms-a52dec 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 GNU Make; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + */ + +static char * a52dec_xpm[] = { +"400 50 83 1", +" c None", +". c #000000", +"+ c #555555", +"@ c #E2E2E2", +"# c #FFFFFF", +"$ c #8D8D8D", +"% c #AAAAAA", +"& c #1C1C1C", +"* c #717171", +"= c #383838", +"- c #999999", +"; c #666666", +"> c #333333", +", c #C6C6C6", +"' c #CCCCCC", +") c #D7D7D7", +"! c #525252", +"~ c #191919", +"{ c #4C4C4C", +"] c #EBEBEB", +"^ c #212121", +"/ c #080808", +"( c #494949", +"_ c #4B4B4B", +": c #323232", +"< c #8A8A8A", +"[ c #252525", +"} c #6B6B6B", +"| c #585858", +"1 c #B0B0B0", +"2 c #3B3B3B", +"3 c #424242", +"4 c #101010", +"5 c #8E8E8E", +"6 c #505050", +"7 c #6A6A6A", +"8 c #696969", +"9 c #9C9C9C", +"0 c #303030", +"a c #7E7E7E", +"b c #565656", +"c c #939393", +"d c #535353", +"e c #707070", +"f c #878787", +"g c #8F8F8F", +"h c #3E3E3E", +"i c #404040", +"j c #676767", +"k c #757575", +"l c #454545", +"m c #747474", +"n c #464646", +"o c #7B7B7B", +"p c #898989", +"q c #626262", +"r c #232323", +"s c #595959", +"t c #5B5B5B", +"u c #7A7A7A", +"v c #111111", +"w c #515151", +"x c #9D9D9D", +"y c #434343", +"z c #2B2B2B", +"A c #A5A5A5", +"B c #7F7F7F", +"C c #2A2A2A", +"D c #4A4A4A", +"E c #818181", +"F c #A8A8A8", +"G c #B1B1B1", +"H c #F5F5F5", +"I c #6F6F6F", +"J c #6D6D6D", +"K c #3A3A3A", +"L c #828282", +"M c #A2A2A2", +"N c #5F5F5F", +"O c #181818", +"P c #A9A9A9", +"Q c #D8D8D8", +"R c #C5C5C5", +"................................................................................................................................................................................................................................................................................................................................................................................................................", +"................................................................................................................................................................................................................................................................................................................................................................................................................", +"..................+@#$............+#+...........................................................................................................................................................................................................................................................................................................................................................................", +".................%####&..........+###*..........................................................................................................................................................................................................................................................................................................................................................................", +"...............&%#####$.........+#####+.........................................................................................................................................................................................................................................................................................................................................................................", +"..............$########=.......+#######+........................................................................................................................................................................................................................................................................................................................................................................", +"............+@#########%......+#########=....................-;-;-;-;-;-;-;-;;.-;-;-;-;-;-;-;-;;...>;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;-;->...............................................................................................................................................................................................................................................", +"..........=,############&....+##########@&...................################'.################'...>############################################################-...............................................................................................................................................................................................................................................", +".........+#######%@#####*...=####@,######,...................################'.################'...>#->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>;#;...............................................................................................................................................................................................................................................", +"........%#####@*&.&#####@..+@###%&.$######+..................###';-;--#######'.########-;-;-###'...>#-........................................................>#-.........................................................................................................................................*%%%%%%%%%$....................&*%,#####%%+.............................&+%,#####,%+&.................", +"......=@####@*.....$#####*+####,....+#####@&.................###'......-#####'.######-......###'...>#;........................................................>#;.........................................................................................................................................###########=.................=,#############$&........................&$#############$&...............", +".....$####@*.......&##########@&.....+#####%.................###'.......-####'.#####;.......###'...>#-........................................................>#-........................................................................................................................................+###########$...............&%################@=......................&@###############@&..............", +"...&,####$..........,########@&.......+#####%................###'........-###'.####;........###'...>#;.....;-;-;->>....>-;-;>..;-;>....;-;-;-;>.;-;>..>;-;....>#;........................................................................................................................................,###########@..............&@###################+....................&@#################@..............", +"...*####,...........+########+.........+#####*...............###'........>###'.###'.........###'...>#-.....########;.;#######;.'##>....########;'##-..'##;....>#-.......................................................................................................................................&#############=............&@#####################&...................,###################*.............", +"....@####&...........@######+..........*######...............###'.........-##'.###-.........###'...>#;.....########'.'########.'##>....########->###.;###.....>#;.......................................................................................................................................*#############%............%######################,..................=########,++$########,.............", +"....&@###,...........*#####+..........+#####@+...............###'.........;##'.###>.........###'...>#-.....##'..>###>###>..'##>'##>....###..;##'.-##-'##;.....>#-.......................................................................................................................................,##############...........=###########,%%##########=.................%#######,....*########.............", +".....+####=..........&####+..........=#####@&................###'.........>##'.###..........###'...>#;.....##'...'##>##'...'##>'##>....###;--##;.>#####'......>#;......................................................................................................................................=#######@#######*..........,#########%&....*########,.................%%@#####+.....########.............", +"......+#)#@...........$##!..........&@####@&.................###'.........>##'.###..........###'...>#-.....##'...'##>##'...'##>'##>....########>..-####>......>#-......................................................................................................................................$#######$#######,.........&#########%.......+########=....................&++%.....&#######,.............", +"......~{{]#*..........=]{{^........&@####@&..................###'.........>##'.###..........###'...>#;.....##'...'##>##'...'##>'##>....###'''##-...###'.......>#;......................................................................................................................................@#######.########&........+########@.........,###,%+&..............................%#######*.............", +"...../{{{%#@&.{{{{.....({{_....:{{{<####@&...................###'.........;##'.###>.........###'...>#-.....##'...###>###...'##>'##>....###..>##'...'##>.......>#-.....................................................................................................................................=#######%.%#######*........%########$.........+*+...............................=+*@#######@..............", +".....[{{{}##$.{{{{.....{{{{/...|{{{1###)2{{{~................###'.........-##'.###;.........###'...>#;.....##'''####.####''###>'##''''>###'''##'...'##>.......>#;.....................................................................................................................................%#######+.+#######@........,########+...........................................%#########@&..............", +".....3{{{{)##&{{{{....4{{{{:...|{{{1##5{{{{{{/...............###'.........###'.###'.........###'...>#-.....########-.;#######-.'######>########-...'##>.......>#-.....................................................................................................................................########...########=.......#########............................................%########$................", +".....6{{7{8##9{{{{~...0{{7{{/..{{{{a#@{{bcb{{[...............###'........-###'.####;........###'...>#;.....''''''';...;-'''-;..-''''''>''''''';....-''>.......>#;....................................................................................................................................+#######,...%#######$.......#########............................................%########@$&..............", +".....d{beb{f#g{{{{h...i{{jk{l/4{{{{m@&b{{no7p=...............###'.......;####'.#####>.......###'...>#-........................................................>#-....................................................................................................................................,#######*...+########.......#########............................................###########@=.............", +".....{{q.o{{m{{b{{h..._{{rsb{l({b{{e&.......###'...>#;........................................................>#;...................................................................................................................................&########&...&########+......#########.....................%%%%%%%%%%%=...........############@&............", +"..../{{t.=7{{{bu{{3...d{b.vo{{{{g{{w..vtxkb{y~...............###'>>>>;'######'.#######';>>>>###'...>#-........................................................>#-...................................................................................................................................*#######@.....,#######,......#########.....................###########+...........+&.&*########%............", +"....z{{b..e7{bA9{{6../{{q..=p{{p@{{{....vtcB{{C..............################'.################'...>#;........................................................>#;...................................................................................................................................,#######$.....*########&.....,########=.........&@$=.......###########+................+########............", +"....D{{2...EFGH@{{|..:{{t...IFF@#7{{...C...(p{{^.............################'.################'...>############################################################-..................................................................................................................................=#######################*.....%########+.........*###@$+....###########+.................@#######+...........", +"...^{{{r..&@###@{{{./{{{b....@###J{{~.^{:~~~l{{_.............''''''''''''''''-.''''''''''''''''-...>'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''';..................................................................................................................................$#######################,.....*########%.........,#######*..###########+.................%#######+...........", +"...(ppp..&@###%.b{{.vcppK....&@##L{{h.D{{{{{{{b}...................................................................................................................................................................................................................................................@########################=....&#########&.......+########+..###########+.....=++$*.......%#######+...........", +"....===.=@###%..q{{/.r==v.....&@#M{{N.(Fpk777pcv..................................................................................................................................................................................................................................................=#########################$.....,########@&.....=@########...%%%%%%%%%%%=.&@#######.......@#######&...........", +".......+####$...}k7O...........=#@B7P+..=teee=................................................>>>>................................................................................................................................................................................................%#########################@.....=##########%+++%#########$.................@#######*.....*#######@............", +"......*####+....vtev............+#QR@#*......................>######-..........'##..........>'####-..........'#'........-#######'.........;##-...........'#'......................................................................................................................................###########################+.....,#######################&.................*########$&.&*########$............", +".....%###@=......................+#####%.....................>#######-.........'##.........>#######-.........'#'........;#######'.........'###>..........'#'.....................................................................................................................................+########$+++++++++$########%.....&@#####################*...................@####################&............", +"....%###@&........................*#####*....................>##;>;###>........'##.........-##-.>###.........'#'........>>>'##>>>........>####;..........'#'.....................................................................................................................................,########&..........#########......=####################%....................+###################+.............", +"...+####*...........&+.............%#####&...................>##>..;##;........'##.........##'...>>>.........'#'...........'##...........-##'#'..........'#'....................................................................................................................................&########,...........%########*......&@#################%......................+#################+..............", +"....@####*.........&@#%............+#####$...................>##>..>##-........'##.........##-..####>........'#'...........'##...........##-;##>.........'#'....................................................................................................................................*########$...........*########,.......&$##############@*........................=@#############@+...............", +"....&@####*.......=@###,&........&,######%...................>##>..;##;........'##.........##'..####>........'#'...........'##..........;##-;##-.........'#'....................................................................................................................................,########=...........&#########&........&*,#########,*&...........................*%#########,*.................", +".....&#####+.....+######@&......+@######%&...................>##>..'##;........'##.........'##>.>-##>........'#'...........'##..........-#######.........'#'................................................................................................................................................................................&+++++&..................................&+++++&....................", +"......+#####+...+########@&....$#######+.....................>##''###'.........'##.........;###''###>........'#'...........'##..........##''''##;........'##''''>...............................................................................................................................................................................................................................................", +".......+#####+.+##########@&&*@######@&......................>######'>.........'##..........-#######>........'#'...........'##.........;##;..>##-........'######>...............................................................................................................................................................................................................................................", +"........%#####%############@########%&.......................>;-;-;;...........;;-...........>-'-;;;>........;;;...........;;-.........;;-....;;-........;-;-;-;>...............................................................................................................................................................................................................................................", +".........%###########*&%###########%............................................................................................................................................................................................................................................................................................................................................................................", +"..........@#########+...%#########%.............................................................................................................................................................................................................................................................................................................................................................................", +"..........&@######@=.....%#######+..............................................................................................................................................................................................................................................................................................................................................................................", +"...........&#####@&.......%####@+...............................................................................................................................................................................................................................................................................................................................................................................", +"............+###@&........&@##%&................................................................................................................................................................................................................................................................................................................................................................................", +".............+#%&..........&,+..................................................................................................................................................................................................................................................................................................................................................................................", +"..............*.................................................................................................................................................................................................................................................................................................................................................................................................", +"................................................................................................................................................................................................................................................................................................................................................................................................................"}; + +