diff options
author | Darren Salt <linux@youmustbejoking.demon.co.uk> | 2009-04-06 00:28:05 +0100 |
---|---|---|
committer | Darren Salt <linux@youmustbejoking.demon.co.uk> | 2009-04-06 00:28:05 +0100 |
commit | 317aec21b9ccbbc288eb428e1d74a51723a2b953 (patch) | |
tree | d984ce931c951d89d9ed4b2cd3ef0dc03cd1a786 /src | |
parent | 699f3239e00a5ff922cf52a22389be0d2fb86bd7 (diff) | |
parent | a6bc7ed17d202107208bbe637ca92d5886c3d686 (diff) | |
download | xine-lib-317aec21b9ccbbc288eb428e1d74a51723a2b953.tar.gz xine-lib-317aec21b9ccbbc288eb428e1d74a51723a2b953.tar.bz2 |
Merge from 1.1.
Diffstat (limited to 'src')
-rw-r--r-- | src/audio_out/Makefile.am | 11 | ||||
-rw-r--r-- | src/audio_out/audio_sndio_out.c | 410 | ||||
-rw-r--r-- | src/demuxers/demux_matroska.c | 36 | ||||
-rw-r--r-- | src/demuxers/demux_mod.c | 10 | ||||
-rw-r--r-- | src/demuxers/id3.c | 9 | ||||
-rw-r--r-- | src/demuxers/matroska.h | 1 | ||||
-rw-r--r-- | src/input/libdvdnav/remap.c | 1 | ||||
-rw-r--r-- | src/xine-engine/info_helper.c | 10 |
8 files changed, 476 insertions, 12 deletions
diff --git a/src/audio_out/Makefile.am b/src/audio_out/Makefile.am index 0ea22c00d..958c87cea 100644 --- a/src/audio_out/Makefile.am +++ b/src/audio_out/Makefile.am @@ -54,6 +54,10 @@ if ENABLE_JACK jack_module = xineplug_ao_out_jack.la endif +if ENABLE_SNDIO +sndio_module = xineplug_ao_out_sndio.la +endif + xineplug_LTLIBRARIES = \ xineplug_ao_out_none.la \ xineplug_ao_out_file.la \ @@ -66,7 +70,8 @@ xineplug_LTLIBRARIES = \ $(pulseaudio_module) \ $(directx2_module) \ $(fusionsound_module) \ - $(jack_module) + $(jack_module) \ + $(sndio_module) xineplug_ao_out_none_la_SOURCES = audio_none_out.c xineplug_ao_out_none_la_LIBADD = $(XINE_LIB) $(LTLIBINTL) @@ -115,3 +120,7 @@ xineplug_ao_out_fusionsound_la_CFLAGS = $(AM_CFLAGS) $(FUSIONSOUND_CFLAGS) xineplug_ao_out_jack_la_SOURCES = audio_jack_out.c xineplug_ao_out_jack_la_LIBADD = $(XINE_LIB) $(JACK_LIBS) $(LTLIBINTL) xineplug_ao_out_jack_la_CFLAGS = $(AM_FLAGS) $(JACK_CFLAGS) + +xineplug_ao_out_sndio_la_SOURCES = audio_sndio_out.c +xineplug_ao_out_sndio_la_LIBADD = $(XINE_LIB) $(SNDIO_LIBS) +xineplug_ao_out_sndio_la_CFLAGS = $(AM_CFLAGS) $(SNDIO_CFLAGS) diff --git a/src/audio_out/audio_sndio_out.c b/src/audio_out/audio_sndio_out.c new file mode 100644 index 000000000..7c3040e6e --- /dev/null +++ b/src/audio_out/audio_sndio_out.c @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2008 Brad Smith <brad@comstyle.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* ao plugin for sndio by Brad Smith <brad@comstyle.com>. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <fcntl.h> +#include <math.h> +#include <unistd.h> +#include <inttypes.h> +#include <pthread.h> + +#include <sndio.h> + +#include "xine_internal.h" +#include "xineutils.h" +#include "audio_out.h" +#include "bswap.h" + +#define GAP_TOLERANCE AO_MAX_GAP +#define PCT_TO_MIDI(p) (((p) * SIO_MAXVOL + 50) / 100) + +typedef struct { + audio_driver_class_t driver_class; + xine_t *xine; +} sndio_class_t; + +typedef struct sndio_driver_s { + ao_driver_t ao_driver; + xine_t *xine; + + struct sio_hdl *hdl; + long long realpos, playpos; + int capabilities; + + int num_channels; + u_int32_t bits_per_sample; + u_int32_t bytes_per_frame; + + struct { + int volume; + int mute; + } mixer; +} sndio_driver_t; + +/* + * Callback to notify of frames processed by the hw. It is + * called from the mail loop called from sio_write(). + */ +static void ao_sndio_onmove_cb(void *addr, int delta) +{ + sndio_driver_t *this = (sndio_driver_t *)addr; + + this->realpos += delta; +} + +/* + * Open the audio device for writing to. + */ +static int ao_sndio_open(ao_driver_t *this_gen, + uint32_t bits, uint32_t rate, int mode) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + struct sio_par par; + + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open bits=%d rate=%d, mode=%d\n", + bits, rate, mode); + + if (this->hdl != NULL) { + sio_close (this->hdl); + this->hdl = NULL; + } + + this->hdl = sio_open(NULL, SIO_PLAY, 0); + if (this->hdl == NULL) + goto bad; + + sio_initpar(&par); + + switch (mode) { + case AO_CAP_MODE_MONO: + par.pchan = 1; + break; + case AO_CAP_MODE_STEREO: + par.pchan = 2; + break; + case AO_CAP_MODE_4CHANNEL: + par.pchan = 4; + break; + case AO_CAP_MODE_4_1CHANNEL: + case AO_CAP_MODE_5CHANNEL: + case AO_CAP_MODE_5_1CHANNEL: + par.pchan = 6; + break; + default: + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open does not support the requested mode: 0x%X\n", + mode); + goto bad; + } + + switch (bits) { + case 8: + par.bits = 8; + par.sig = 0; + break; + case 16: + par.bits = 16; + par.sig = 1; + break; + default: + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open bits per sample not supported: %d\n", bits); + goto bad; + } + + par.rate = rate; + par.appbufsz = par.rate * 250 / 1000; /* 250ms buffer */ + + if (!sio_setpar(this->hdl, &par)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open could not set params\n"); + goto bad; + } + + if (!sio_getpar(this->hdl, &par)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open could not get params\n"); + goto bad; + } + + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open %d channels output\n", + par.pchan); + + this->num_channels = par.pchan; + this->bytes_per_frame = par.bps * par.pchan; + this->playpos = 0; + this->realpos = 0; + sio_onmove(this->hdl, ao_sndio_onmove_cb, this); + + if (!sio_start(this->hdl)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_open could not start\n"); + goto bad; + } + + return par.rate; + +bad: + if (this->hdl != NULL) + sio_close(this->hdl); + return 0; +} + +static int ao_sndio_num_channels(ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + return this->num_channels; +} + +static int ao_sndio_bytes_per_frame(ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + return this->bytes_per_frame; +} + +static int ao_sndio_get_gap_tolerance (ao_driver_t *this_gen) +{ + return GAP_TOLERANCE; +} + +static int ao_sndio_write(ao_driver_t *this_gen, int16_t *data, + uint32_t num_frames) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + size_t ret, size = num_frames * this->bytes_per_frame; + + ret = sio_write(this->hdl, data, size); + if (ret == 0) + return 0; + + this->playpos += num_frames; + + return 1; +} + +static int ao_sndio_delay (ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + int bufused; + + if (this->realpos < 0) + bufused = this->playpos; + else + bufused = this->playpos - this->realpos; + + return bufused; +} + +static void ao_sndio_close(ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_close called\n"); + + if (!sio_stop(this->hdl)) { + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_close could not stop\n"); + } + + sio_close(this->hdl); + this->hdl = NULL; +} + +static uint32_t ao_sndio_get_capabilities (ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + return this->capabilities; +} + +static void ao_sndio_exit(ao_driver_t *this_gen) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + xprintf (this->xine, XINE_VERBOSITY_DEBUG, + "audio_sndio_out: ao_sndio_exit called\n"); + + if (this->hdl != NULL) + sio_close(this->hdl); +} + +static int ao_sndio_get_property (ao_driver_t *this_gen, int property) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + switch (property) { + case AO_PROP_MIXER_VOL: + return this->mixer.volume; + break; + case AO_PROP_MUTE_VOL: + return this->mixer.mute; + break; + } + + return 0; +} + +static int ao_sndio_set_property (ao_driver_t *this_gen, int property, int value) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + int vol; + + if (this->hdl == NULL) + return 0; + + switch(property) { + case AO_PROP_MIXER_VOL: + this->mixer.volume = value; + if (!this->mixer.mute) + sio_setvol(this->hdl, PCT_TO_MIDI(this->mixer.volume)); + return this->mixer.volume; + break; + + case AO_PROP_MUTE_VOL: + this->mixer.mute = (value) ? 1 : 0; + vol = 0; + if (!this->mixer.mute) + vol = PCT_TO_MIDI(this->mixer.volume); + sio_setvol(this->hdl, vol); + return value; + break; + } + + return value; +} + +/* + * pause, resume, flush buffers + */ +static int ao_sndio_ctrl(ao_driver_t *this_gen, int cmd, ...) +{ + sndio_driver_t *this = (sndio_driver_t *) this_gen; + + /* + * sndio pauses automatically if there are no more samples to play + * and resumes when there are samples again. So we leave this empty + * for the moment. + */ + + return 0; +} + +static ao_driver_t *open_plugin (audio_driver_class_t *class_gen, const void *data) +{ + sndio_class_t *class = (sndio_class_t *) class_gen; + sndio_driver_t *this; + + lprintf ("audio_sndio_out: open_plugin called\n"); + + this = calloc(1, sizeof (sndio_driver_t)); + if (!this) + return NULL; + + this->xine = class->xine; + + /* + * Set capabilities + */ + this->capabilities = AO_CAP_MODE_MONO | AO_CAP_MODE_STEREO | + AO_CAP_MODE_4CHANNEL | AO_CAP_MODE_4_1CHANNEL | + AO_CAP_MODE_5CHANNEL | AO_CAP_MODE_5_1CHANNEL | + AO_CAP_MIXER_VOL | AO_CAP_MUTE_VOL | AO_CAP_8BITS | + AO_CAP_16BITS; + + this->ao_driver.get_capabilities = ao_sndio_get_capabilities; + this->ao_driver.get_property = ao_sndio_get_property; + this->ao_driver.set_property = ao_sndio_set_property; + this->ao_driver.open = ao_sndio_open; + this->ao_driver.num_channels = ao_sndio_num_channels; + this->ao_driver.bytes_per_frame = ao_sndio_bytes_per_frame; + this->ao_driver.delay = ao_sndio_delay; + this->ao_driver.write = ao_sndio_write; + this->ao_driver.close = ao_sndio_close; + this->ao_driver.exit = ao_sndio_exit; + this->ao_driver.get_gap_tolerance = ao_sndio_get_gap_tolerance; + this->ao_driver.control = ao_sndio_ctrl; + + return &this->ao_driver; +} + +/* + * class functions + */ + +static char* get_identifier (audio_driver_class_t *this_gen) +{ + return "sndio"; +} + +static char* get_description (audio_driver_class_t *this_gen) +{ + return _("xine audio output plugin using sndio audio devices/drivers "); +} + +static void dispose_class (audio_driver_class_t *this_gen) +{ + sndio_class_t *this = (sndio_class_t *) this_gen; + + free(this); +} + +static void *init_class (xine_t *xine, void *data) +{ + sndio_class_t *this; + + lprintf ("audio_sndio_out: init class\n"); + + this = calloc(1, sizeof (sndio_class_t)); + if (!this) + return NULL; + + this->driver_class.open_plugin = open_plugin; + this->driver_class.get_identifier = get_identifier; + this->driver_class.get_description = get_description; + this->driver_class.dispose = dispose_class; + + this->xine = xine; + + return this; +} + +static const ao_info_t ao_info_sndio = { + 12 +}; + +/* + * exported plugin catalog entry + */ + +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_AUDIO_OUT, 8, "sndio", XINE_VERSION_CODE, &ao_info_sndio, init_class }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; diff --git a/src/demuxers/demux_matroska.c b/src/demuxers/demux_matroska.c index bdc30df30..829581925 100644 --- a/src/demuxers/demux_matroska.c +++ b/src/demuxers/demux_matroska.c @@ -2064,6 +2064,31 @@ static int parse_block (demux_matroska_t *this, size_t block_size, return 1; } +static int parse_simpleblock(demux_matroska_t *this, size_t block_len, uint64_t cluster_timecode, uint64_t block_duration) +{ + int has_block = 0; + off_t block_pos = 0; + off_t file_len = 0; + int normpos = 0; + int is_key = 1; + + lprintf("simpleblock\n"); + block_pos = this->input->get_current_pos(this->input); + file_len = this->input->get_length(this->input); + if( file_len ) + normpos = (int) ( (double) block_pos * 65535 / file_len ); + + if (!read_block_data(this, block_len)) + return 0; + + has_block = 1; + /* we have the duration, we can parse the block now */ + if (!parse_block(this, block_len, cluster_timecode, block_duration, + normpos, is_key)) + return 0; + return 1; +} + static int parse_block_group(demux_matroska_t *this, uint64_t cluster_timecode, uint64_t cluster_duration) { @@ -2128,7 +2153,8 @@ static int parse_block_group(demux_matroska_t *this, static int parse_cluster(demux_matroska_t *this) { ebml_parser_t *ebml = this->ebml; - int next_level = 2; + int this_level = ebml->level; + int next_level = this_level; uint64_t timecode = 0; uint64_t duration = 0; @@ -2145,7 +2171,7 @@ static int parse_cluster(demux_matroska_t *this) { this->first_cluster_found = 1; } - while (next_level == 2) { + while (next_level == this_level) { ebml_elem_t elem; if (!ebml_read_elem_head(ebml, &elem)) @@ -2169,6 +2195,11 @@ static int parse_cluster(demux_matroska_t *this) { if ((elem.len > 0) && !parse_block_group(this, timecode, duration)) return 0; break; + case MATROSKA_ID_CL_SIMPLEBLOCK: + lprintf("simpleblock\n"); + if (!parse_simpleblock(this, elem.len, timecode, duration)) + return 0; + break; case MATROSKA_ID_CL_BLOCK: lprintf("block\n"); if (!ebml_skip(ebml, &elem)) @@ -2315,6 +2346,7 @@ static int parse_top_level_head(demux_matroska_t *this, int *next_level) { ebml_elem_t elem; int ret_value = 1; off_t current_pos; + current_pos = this->input->get_current_pos(this->input); lprintf("current_pos: %" PRIdMAX "\n", (intmax_t)current_pos); diff --git a/src/demuxers/demux_mod.c b/src/demuxers/demux_mod.c index e8199be0e..cd55f6781 100644 --- a/src/demuxers/demux_mod.c +++ b/src/demuxers/demux_mod.c @@ -366,11 +366,11 @@ static void *demux_mod_init_plugin (xine_t *xine, void *data) { "audio/x-s3m: s3m: ScreamTracker 3 Module;" "audio/s3m: s3m: ScreamTracker 3 Module;" "application/playerpro: 669: 669 Tracker Module;" - "application/adrift; amf: ADRIFT Module File;" - "audio/med; med; Amiga MED/OctaMED Tracker Module Sound File;" - "audio/x-amf; amf: ADRIFT Module File;" - "audio/x-xm; xm: FastTracker II Audio;" - "audio/xm; xm: FastTracker II Audio;"; + "application/adrift: amf: ADRIFT Module File;" + "audio/med: med: Amiga MED/OctaMED Tracker Module Sound File;" + "audio/x-amf: amf: ADRIFT Module File;" + "audio/x-xm: xm: FastTracker II Audio;" + "audio/xm: xm: FastTracker II Audio;"; this->demux_class.extensions = "mod it stm s3m 669 amf med mdl xm"; this->demux_class.dispose = default_demux_class_dispose; diff --git a/src/demuxers/id3.c b/src/demuxers/id3.c index ab15184af..1919239e6 100644 --- a/src/demuxers/id3.c +++ b/src/demuxers/id3.c @@ -273,11 +273,12 @@ static int id3v22_parse_frame_header(input_plugin_t *input, static int id3v22_interp_frame(input_plugin_t *input, xine_stream_t *stream, id3v22_frame_header_t *frame_header) { - char buf[frame_header->size + 1]; + char buf[frame_header->size + 2]; int enc; if (input->read (input, buf, frame_header->size) == frame_header->size) { buf[frame_header->size] = 0; + buf[frame_header->size + 1] = 0; enc = buf[0]; if( enc >= ID3_ENCODING_COUNT ) enc = 0; @@ -459,11 +460,12 @@ static int id3v23_parse_frame_ext_header(input_plugin_t *input, static int id3v23_interp_frame(input_plugin_t *input, xine_stream_t *stream, id3v23_frame_header_t *frame_header) { - char buf[frame_header->size + 1]; + char buf[frame_header->size + 2]; int enc; if (input->read (input, buf, frame_header->size) == frame_header->size) { buf[frame_header->size] = 0; + buf[frame_header->size + 1] = 0; enc = buf[0]; if( enc >= ID3_ENCODING_COUNT ) enc = 0; @@ -702,11 +704,12 @@ static int id3v24_parse_ext_header(input_plugin_t *input, static int id3v24_interp_frame(input_plugin_t *input, xine_stream_t *stream, id3v24_frame_header_t *frame_header) { - char buf[frame_header->size + 1]; + char buf[frame_header->size + 2]; int enc; if (input->read (input, buf, frame_header->size) == frame_header->size) { buf[frame_header->size] = 0; + buf[frame_header->size + 1] = 0; enc = buf[0]; if( enc >= ID3_ENCODING_COUNT ) enc = 0; diff --git a/src/demuxers/matroska.h b/src/demuxers/matroska.h index 387205723..50583df9c 100644 --- a/src/demuxers/matroska.h +++ b/src/demuxers/matroska.h @@ -62,6 +62,7 @@ #define MATROSKA_ID_CL_BLOCKGROUP 0xA0 #define MATROSKA_ID_CL_BLOCK 0xA1 #define MATROSKA_ID_CL_BLOCKVIRTUAL 0xA2 +#define MATROSKA_ID_CL_SIMPLEBLOCK 0xA3 #define MATROSKA_ID_CL_BLOCKADDITIONS 0x75A1 #define MATROSKA_ID_CL_BLOCKMORE 0xA6 #define MATROSKA_ID_CL_BLOCKADDID 0xEE diff --git a/src/input/libdvdnav/remap.c b/src/input/libdvdnav/remap.c index 43c81c66f..df0be29ce 100644 --- a/src/input/libdvdnav/remap.c +++ b/src/input/libdvdnav/remap.c @@ -216,6 +216,7 @@ remap_t* remap_loadmap( char *title) { remap_add_node( map, tmp); } } + close (fp); /* ignoring errors... */ if (map->nblocks == 0 && map->debug == 0) return NULL; return map; diff --git a/src/xine-engine/info_helper.c b/src/xine-engine/info_helper.c index b4a4bca83..2b09dcd3b 100644 --- a/src/xine-engine/info_helper.c +++ b/src/xine-engine/info_helper.c @@ -251,7 +251,15 @@ static void meta_info_set_unlocked_encoding(xine_stream_t *stream, int info, con size_t inbytesleft, outbytesleft; inbuf = (ICONV_CONST char *)value; - inbytesleft = strlen(value); + if (!strncmp (enc, "UTF-16", 6) || !strncmp (enc, "UCS-2", 5)) + { + /* strlen() won't work with UTF-16* or UCS-2* */ + inbytesleft = 0; + while (value[inbytesleft] || value[inbytesleft + 1]) + inbytesleft += 2; + } /* ... do we need to handle UCS-4? Probably not. */ + else + inbytesleft = strlen(value); outbytesleft = 4 * inbytesleft; /* estimative (max) */ outbuf = utf8_value = malloc(outbytesleft+1); |