From b82a1365fcbfb32c4e24dfdc607b685d09c4d520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20=27Flameeyes=27=20Petten=C3=B2?= Date: Thu, 31 May 2007 16:55:55 +0200 Subject: Create a single NSF plugin that includes both the demuxer (previously in the audio group) and the decoder. One of the two plugins without the other would be useless. --HG-- rename : src/libxineadec/nsf.c => src/combined/nsf_decoder.c rename : src/demuxers/demux_nsf.c => src/combined/nsf_demuxer.c --- ChangeLog | 1 + src/combined/Makefile.am | 11 +- src/combined/nsf_combined.c | 46 ++++++ src/combined/nsf_decoder.c | 268 ++++++++++++++++++++++++++++++ src/combined/nsf_demuxer.c | 391 +++++++++++++++++++++++++++++++++++++++++++ src/demuxers/Makefile.am | 2 +- src/demuxers/demux_nsf.c | 392 -------------------------------------------- src/demuxers/group_audio.c | 5 - src/demuxers/group_audio.h | 1 - src/libxineadec/Makefile.am | 9 - src/libxineadec/nsf.c | 295 --------------------------------- 11 files changed, 717 insertions(+), 704 deletions(-) create mode 100644 src/combined/nsf_combined.c create mode 100644 src/combined/nsf_decoder.c create mode 100644 src/combined/nsf_demuxer.c delete mode 100644 src/demuxers/demux_nsf.c delete mode 100644 src/libxineadec/nsf.c diff --git a/ChangeLog b/ChangeLog index 4f7aa3e2b..448894166 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,7 @@ xine-lib (1.1.90) (Unreleased) * Add another message code to allow for auth prompts. Previously, it was not possible to distinguish between 401 Authentication Requried and 403 Forbidden. + * Merge the demuxer and the decoder for NSF files in a combined plugin. xine-lib (1.1.7) (unreleased) * Support libdca (new name for libdts) by shuffling around the dts.h file. diff --git a/src/combined/Makefile.am b/src/combined/Makefile.am index ed513cd4d..fef159564 100644 --- a/src/combined/Makefile.am +++ b/src/combined/Makefile.am @@ -11,7 +11,11 @@ if ENABLE_LIBFLAC xineplug_flac = xineplug_flac.la endif -xineplug_LTLIBRARIES = $(xineplug_wavpack) $(xineplug_flac) +$(top_builddir)/contrib/nosefart/libnosefart.la: + $(MAKE) -C $(top_builddir)/contrib/nosefart + +xineplug_LTLIBRARIES = $(xineplug_wavpack) $(xineplug_flac) \ + xineplug_nsf.la xineplug_wavpack_la_SOURCES = demux_wavpack.c decoder_wavpack.c combined_wavpack.c combined_wavpack.h xineplug_wavpack_la_LIBADD = $(XINE_LIB) $(WAVPACK_LIBS) @@ -21,3 +25,8 @@ xineplug_wavpack_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/demuxers xineplug_flac_la_SOURCES = demux_flac.c decoder_flac.c demux_flac.h xineplug_flac_la_LIBADD = $(XINE_LIB) $(LIBFLAC_LIBS) xineplug_flac_la_CFLAGS = $(AM_CFLAGS) $(LIBFLAC_CFLAGS) + +xineplug_nsf_la_SOURCES = nsf_decoder.c nsf_demuxer.c nsf_combined.c +xineplug_nsf_la_LIBADD = $(XINE_LIB) $(top_builddir)/contrib/nosefart/libnosefart.la -lm +xineplug_nsf_la_CFLAGS = $(AM_CFLAGS) -fno-strict-aliasing +xineplug_nsf_la_CPPFLAGS = $(AM_CPPFLAGS) -DNSF_PLAYER -I$(top_srcdir)/contrib/nosefart -I$(top_srcdir)/src/demuxers diff --git a/src/combined/nsf_combined.c b/src/combined/nsf_combined.c new file mode 100644 index 000000000..855b8d2a5 --- /dev/null +++ b/src/combined/nsf_combined.c @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2007 the xine project + * + * This file is part of xine, a free video player. + * + * xine 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. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * $Id: combined_wavpack.c,v 1.3 2007/03/17 07:34:02 dgp85 Exp $ + */ + +#include "xine_internal.h" + +void *decoder_nsf_init_plugin (xine_t *xine, void *data); +void *demux_nsf_init_plugin (xine_t *xine, void *data); + +static const demuxer_info_t demux_info_nsf = { + 10 /* priority */ +}; + +static uint32_t audio_types[] = { + BUF_AUDIO_NSF, + 0 +}; + +static const decoder_info_t decoder_info_nsf = { + audio_types, /* supported types */ + 5 /* priority */ +}; + +const plugin_info_t xine_plugin_info[] EXPORTED = { + { PLUGIN_DEMUX, 26, "nsfdemux", XINE_VERSION_CODE, &demux_info_nsf, demux_nsf_init_plugin }, + { PLUGIN_AUDIO_DECODER, 15, "nsfdec", XINE_VERSION_CODE, &decoder_info_nsf, decoder_nsf_init_plugin }, + { PLUGIN_NONE, 0, NULL, 0, NULL, NULL } +}; diff --git a/src/combined/nsf_decoder.c b/src/combined/nsf_decoder.c new file mode 100644 index 000000000..e8b5dd96a --- /dev/null +++ b/src/combined/nsf_decoder.c @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2000-2001 the xine project + * + * This file is part of xine, a free video player. + * + * xine 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. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * NSF Audio "Decoder" using the Nosefart NSF engine by Matt Conte + * http://www.baisoku.org/ + * + * $Id: nsf.c,v 1.13 2006/09/25 23:56:31 dgp85 Exp $ + */ + +#include +#include +#include +#include +#include + +#include "xine_internal.h" +#include "audio_out.h" +#include "buffer.h" +#include "xineutils.h" +#include "bswap.h" + +/* Nosefart includes */ +#include "types.h" +#include "nsf.h" + +typedef struct { + audio_decoder_class_t decoder_class; +} nsf_class_t; + +typedef struct nsf_decoder_s { + audio_decoder_t audio_decoder; + + xine_stream_t *stream; + + int sample_rate; /* audio sample rate */ + int bits_per_sample; /* bits/sample, usually 8 or 16 */ + int channels; /* 1 or 2, usually */ + + int output_open; /* flag to indicate audio is ready */ + + int nsf_size; + unsigned char *nsf_file; + int nsf_index; + int song_number; + + /* nsf-specific variables */ + int64_t last_pts; + unsigned int iteration; + + nsf_t *nsf; +} nsf_decoder_t; + +/************************************************************************** + * xine audio plugin functions + *************************************************************************/ + +static void nsf_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { + + nsf_decoder_t *this = (nsf_decoder_t *) this_gen; + audio_buffer_t *audio_buffer; + + if (buf->decoder_flags & BUF_FLAG_HEADER) { + + /* When the engine sends a BUF_FLAG_HEADER flag, it is time to initialize + * the decoder. The buffer element type has 4 decoder_info fields, + * 0..3. Field 1 is the sample rate. Field 2 is the bits/sample. Field + * 3 is the number of channels. */ + this->sample_rate = buf->decoder_info[1]; + this->bits_per_sample = buf->decoder_info[2]; + this->channels = buf->decoder_info[3]; + + /* take this opportunity to initialize stream/meta information */ + _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, + "NES Music (Nosefart)"); + + this->song_number = buf->content[4]; + /* allocate a buffer for the file */ + this->nsf_size = BE_32(&buf->content[0]); + this->nsf_file = xine_xmalloc(this->nsf_size); + this->nsf_index = 0; + + /* peform any other required initialization */ + this->last_pts = -1; + this->iteration = 0; + + return; + } + + /* accumulate chunks from the NSF file until whole file is received */ + if (this->nsf_index < this->nsf_size) { + xine_fast_memcpy(&this->nsf_file[this->nsf_index], buf->content, + buf->size); + this->nsf_index += buf->size; + + if (this->nsf_index == this->nsf_size) { + /* file has been received, proceed to initialize engine */ + nsf_init(); + this->nsf = nsf_load(NULL, this->nsf_file, this->nsf_size); + if (!this->nsf) { + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "nsf: could not initialize NSF\n"); + /* make the decoder return on every subsequent buffer */ + this->nsf_index = 0; + return; + } + this->nsf->current_song = this->song_number; + nsf_playtrack(this->nsf, this->nsf->current_song, this->sample_rate, + this->bits_per_sample, this->channels); + } + return; + } + + /* if the audio output is not open yet, open the audio output */ + if (!this->output_open) { + this->output_open = this->stream->audio_out->open( + this->stream->audio_out, + this->stream, + this->bits_per_sample, + this->sample_rate, + _x_ao_channels2mode(this->channels)); + } + + /* if the audio still isn't open, do not go any further with the decode */ + if (!this->output_open) + return; + + /* check if a song change was requested */ + if (buf->decoder_info[1]) { + this->nsf->current_song = buf->decoder_info[1]; + nsf_playtrack(this->nsf, this->nsf->current_song, this->sample_rate, + this->bits_per_sample, this->channels); + } + + /* time to decode a frame */ + if (this->last_pts != -1) { + + /* process a frame */ + nsf_frame(this->nsf); + + /* get an audio buffer */ + audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); + if (audio_buffer->mem_size == 0) { + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "nsf: Help! Allocated audio buffer with nothing in it!\n"); + return; + } + + apu_process(audio_buffer->mem, this->sample_rate / this->nsf->playback_rate); + audio_buffer->vpts = buf->pts; + audio_buffer->num_frames = this->sample_rate / this->nsf->playback_rate; + this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); + } + this->last_pts = buf->pts; +} + +/* This function resets the state of the audio decoder. This usually + * entails resetting the data accumulation buffer. */ +static void nsf_reset (audio_decoder_t *this_gen) { + + nsf_decoder_t *this = (nsf_decoder_t *) this_gen; + + this->last_pts = -1; +} + +/* This function resets the last pts value of the audio decoder. */ +static void nsf_discontinuity (audio_decoder_t *this_gen) { + + nsf_decoder_t *this = (nsf_decoder_t *) this_gen; + + this->last_pts = -1; +} + +/* This function closes the audio output and frees the private audio decoder + * structure. */ +static void nsf_dispose (audio_decoder_t *this_gen) { + + nsf_decoder_t *this = (nsf_decoder_t *) this_gen; + + /* close the audio output */ + if (this->output_open) + this->stream->audio_out->close (this->stream->audio_out, this->stream); + this->output_open = 0; + + /* free anything that was allocated during operation */ + nsf_free(&this->nsf); + free(this->nsf_file); + free(this); +} + +/* This function allocates, initializes, and returns a private audio + * decoder structure. */ +static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) { + + nsf_decoder_t *this ; + + this = (nsf_decoder_t *) xine_xmalloc (sizeof (nsf_decoder_t)); + + /* connect the member functions */ + this->audio_decoder.decode_data = nsf_decode_data; + this->audio_decoder.reset = nsf_reset; + this->audio_decoder.discontinuity = nsf_discontinuity; + this->audio_decoder.dispose = nsf_dispose; + + /* connect the stream */ + this->stream = stream; + + /* audio output is not open at the start */ + this->output_open = 0; + + /* initialize the basic audio parameters */ + this->channels = 0; + this->sample_rate = 0; + this->bits_per_sample = 0; + + /* return the newly-initialized audio decoder */ + return &this->audio_decoder; +} + +/* This function returns a brief string that describes (usually with the + * decoder's most basic name) the audio decoder plugin. */ +static char *get_identifier (audio_decoder_class_t *this) { + return "NSF"; +} + +/* This function returns a slightly longer string describing the audio + * decoder plugin. */ +static char *get_description (audio_decoder_class_t *this) { + return "NES Music audio decoder plugin"; +} + +/* This function frees the audio decoder class and any other memory that was + * allocated. */ +static void dispose_class (audio_decoder_class_t *this_gen) { + + nsf_class_t *this = (nsf_class_t *)this_gen; + + free (this); +} + +/* This function allocates a private audio decoder class and initializes + * the class's member functions. */ +void *decoder_nsf_init_plugin (xine_t *xine, void *data) { + + nsf_class_t *this ; + + this = (nsf_class_t *) xine_xmalloc (sizeof (nsf_class_t)); + + this->decoder_class.open_plugin = open_plugin; + this->decoder_class.get_identifier = get_identifier; + this->decoder_class.get_description = get_description; + this->decoder_class.dispose = dispose_class; + + return this; +} diff --git a/src/combined/nsf_demuxer.c b/src/combined/nsf_demuxer.c new file mode 100644 index 000000000..b598b9e1c --- /dev/null +++ b/src/combined/nsf_demuxer.c @@ -0,0 +1,391 @@ +/* + * Copyright (C) 2000-2003 the xine project + * + * This file is part of xine, a free video player. + * + * xine 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. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +/* + * NSF File "Demuxer" by Mike Melanson (melanson@pcisys.net) + * This is really just a loader for NES Music File Format (extension NSF) + * which loads an entire NSF file and passes it over to the NSF audio + * decoder. + * + * After the file is sent over, the demuxer controls the playback by + * sending empty buffers with incrementing pts values. + * + * For more information regarding the NSF format, visit: + * http://www.tripoint.org/kevtris/nes/nsfspec.txt + * + * $Id: demux_nsf.c,v 1.24 2007/03/29 17:03:06 dgp85 Exp $ + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +/********** logging **********/ +#define LOG_MODULE "demux_nsf" +/* #define LOG_VERBOSE */ +/* #define LOG */ + +#include "xine_internal.h" +#include "xineutils.h" +#include "compat.h" +#include "demux.h" +#include "bswap.h" + +#define NSF_HEADER_SIZE 0x80 +#define NSF_SAMPLERATE 44100 +#define NSF_BITS 8 +#define NSF_CHANNELS 1 +#define NSF_REFRESH_RATE 60 +#define NSF_PTS_INC (90000 / NSF_REFRESH_RATE) + +typedef struct { + demux_plugin_t demux_plugin; + + xine_stream_t *stream; + fifo_buffer_t *video_fifo; + fifo_buffer_t *audio_fifo; + input_plugin_t *input; + int status; + + int total_songs; + int current_song; + int new_song; /* indicates song change */ + + char *title; + char *artist; + char *copyright; + + off_t filesize; + + int64_t current_pts; + int file_sent; +} demux_nsf_t; + +typedef struct { + demux_class_t demux_class; +} demux_nsf_class_t; + +/* returns 1 if the NSF file was opened successfully, 0 otherwise */ +static int open_nsf_file(demux_nsf_t *this) { + unsigned char header[NSF_HEADER_SIZE]; + + this->input->seek(this->input, 0, SEEK_SET); + if (this->input->read(this->input, header, NSF_HEADER_SIZE) != + NSF_HEADER_SIZE) + return 0; + + /* check for the signature */ + if ((header[0] != 'N') || + (header[1] != 'E') || + (header[2] != 'S') || + (header[3] != 'M') || + (header[4] != 0x1A)) + return 0; + + this->total_songs = header[6]; + this->current_song = header[7]; + this->title = strdup(&header[0x0E]); + this->artist = strdup(&header[0x2E]); + this->copyright = strdup(&header[0x4E]); + + this->filesize = this->input->get_length(this->input); + + return 1; +} + +static int demux_nsf_send_chunk(demux_plugin_t *this_gen) { + demux_nsf_t *this = (demux_nsf_t *) this_gen; + buf_element_t *buf; + int bytes_read; + char title[100]; + + /* send chunks of the file to the decoder until file is completely + * loaded; then send control buffers */ + if (!this->file_sent) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_AUDIO_NSF; + bytes_read = this->input->read(this->input, buf->content, buf->max_size); + + if (bytes_read == 0) { + /* the file has been completely loaded, free the buffer and start + * sending control buffers */ + buf->free_buffer(buf); + this->file_sent = 1; + + } else { + + /* keep loading the file */ + if (bytes_read < buf->max_size) + buf->size = bytes_read; + else + buf->size = buf->max_size; + + buf->extra_info->input_normpos = 0; + buf->extra_info->input_time = 0; + buf->pts = 0; + + this->audio_fifo->put (this->audio_fifo, buf); + } + } + + /* this is not an 'else' because control might fall through from above */ + if (this->file_sent) { + /* send a control buffer */ + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + + if (this->new_song) { + + buf->decoder_info[1] = this->current_song; + this->new_song = 0; + sprintf(title, "%s, song %d/%d", + this->title, this->current_song, this->total_songs); + + _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, title); + + _x_demux_control_newpts(this->stream, this->current_pts, 0); + + } else + buf->decoder_info[1] = 0; + + buf->type = BUF_AUDIO_NSF; + if(this->total_songs) + buf->extra_info->input_normpos = (this->current_song - 1) * 65535 / this->total_songs; + buf->extra_info->input_time = this->current_pts / 90; + buf->pts = this->current_pts; + buf->size = 0; + this->audio_fifo->put (this->audio_fifo, buf); + + this->current_pts += NSF_PTS_INC; + } + + return this->status; +} + +static void demux_nsf_send_headers(demux_plugin_t *this_gen) { + demux_nsf_t *this = (demux_nsf_t *) this_gen; + buf_element_t *buf; + char copyright[100]; + + this->video_fifo = this->stream->video_fifo; + this->audio_fifo = this->stream->audio_fifo; + + this->status = DEMUX_OK; + + /* load stream information */ + _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 0); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_CHANNELS, + NSF_CHANNELS); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE, + NSF_SAMPLERATE); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITS, + NSF_BITS); + + _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, this->title); + _x_meta_info_set(this->stream, XINE_META_INFO_ARTIST, this->artist); + sprintf(copyright, "(C) %s", this->copyright); + _x_meta_info_set(this->stream, XINE_META_INFO_COMMENT, copyright); + + /* send start buffers */ + _x_demux_control_start(this->stream); + + /* send init info to the audio decoder */ + if (this->audio_fifo) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_AUDIO_NSF; + buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_FRAME_END; + buf->decoder_info[0] = 5; + buf->decoder_info[1] = NSF_SAMPLERATE; + buf->decoder_info[2] = NSF_BITS; + buf->decoder_info[3] = NSF_CHANNELS; + + /* send the NSF filesize in the body, big endian format */ + buf->content[0] = (this->filesize >> 24) & 0xFF; + buf->content[1] = (this->filesize >> 16) & 0xFF; + buf->content[2] = (this->filesize >> 8) & 0xFF; + buf->content[3] = (this->filesize >> 0) & 0xFF; + /* send the requested song */ + buf->content[4] = this->current_song + 5; + + this->audio_fifo->put (this->audio_fifo, buf); + } +} + +static int demux_nsf_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time, int playing) { + + demux_nsf_t *this = (demux_nsf_t *) this_gen; + start_pos = (off_t) ( (double) start_pos / 65535 * + this->total_songs ); + + /* if thread is not running, initialize demuxer */ + if( !playing ) { + + /* send new pts */ + _x_demux_control_newpts(this->stream, 0, 0); + + this->status = DEMUX_OK; + + /* reposition stream at the start for loading */ + this->input->seek(this->input, 0, SEEK_SET); + + this->file_sent = 0; + this->current_pts = 0; + this->new_song = 1; + } else { + this->current_song = start_pos + 1; + this->new_song = 1; + this->current_pts = 0; + _x_demux_flush_engine(this->stream); + } + + return this->status; +} + +static void demux_nsf_dispose (demux_plugin_t *this_gen) { + demux_nsf_t *this = (demux_nsf_t *) this_gen; + + free(this->title); + free(this->artist); + free(this->copyright); + free(this); +} + +static int demux_nsf_get_status (demux_plugin_t *this_gen) { + demux_nsf_t *this = (demux_nsf_t *) this_gen; + + return this->status; +} + +/* return the approximate length in miliseconds */ +static int demux_nsf_get_stream_length (demux_plugin_t *this_gen) { + return 0; +} + +static uint32_t demux_nsf_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_nsf_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + +static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, + input_plugin_t *input) { + + demux_nsf_t *this; + + if (!INPUT_IS_SEEKABLE(input)) { + xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "input not seekable, can not handle!\n"); + return NULL; + } + + this = xine_xmalloc (sizeof (demux_nsf_t)); + this->stream = stream; + this->input = input; + + this->demux_plugin.send_headers = demux_nsf_send_headers; + this->demux_plugin.send_chunk = demux_nsf_send_chunk; + this->demux_plugin.seek = demux_nsf_seek; + this->demux_plugin.dispose = demux_nsf_dispose; + this->demux_plugin.get_status = demux_nsf_get_status; + this->demux_plugin.get_stream_length = demux_nsf_get_stream_length; + this->demux_plugin.get_capabilities = demux_nsf_get_capabilities; + this->demux_plugin.get_optional_data = demux_nsf_get_optional_data; + this->demux_plugin.demux_class = class_gen; + + this->status = DEMUX_FINISHED; + + switch (stream->content_detection_method) { + + case METHOD_BY_EXTENSION: { + const char *extensions, *mrl; + + mrl = input->get_mrl (input); + extensions = class_gen->get_extensions (class_gen); + + if (!_x_demux_check_extension (mrl, extensions)) { + free (this); + return NULL; + } + } + /* falling through is intended */ + + case METHOD_BY_CONTENT: + case METHOD_EXPLICIT: + + if (!open_nsf_file(this)) { + free (this); + return NULL; + } + + break; + + default: + free (this); + return NULL; + } + + return &this->demux_plugin; +} + +static const char *get_description (demux_class_t *this_gen) { + return "NES Music file demux plugin"; +} + +static const char *get_identifier (demux_class_t *this_gen) { + return "NSF"; +} + +static const char *get_extensions (demux_class_t *this_gen) { + return "nsf"; +} + +static const char *get_mimetypes (demux_class_t *this_gen) { + return NULL; +} + +static void class_dispose (demux_class_t *this_gen) { + demux_nsf_class_t *this = (demux_nsf_class_t *) this_gen; + + free (this); +} + +void *demux_nsf_init_plugin (xine_t *xine, void *data) { + demux_nsf_class_t *this; + + this = xine_xmalloc (sizeof (demux_nsf_class_t)); + + this->demux_class.open_plugin = open_plugin; + this->demux_class.get_description = get_description; + this->demux_class.get_identifier = get_identifier; + this->demux_class.get_mimetypes = get_mimetypes; + this->demux_class.get_extensions = get_extensions; + this->demux_class.dispose = class_dispose; + + return this; +} diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am index b1e747bcc..b57dc7369 100644 --- a/src/demuxers/Makefile.am +++ b/src/demuxers/Makefile.am @@ -111,7 +111,7 @@ xineplug_dmx_games_la_SOURCES = group_games.c demux_eawve.c \ xineplug_dmx_games_la_LIBADD = $(XINE_LIB) xineplug_dmx_audio_la_SOURCES = group_audio.c demux_aud.c demux_aiff.c \ - demux_cdda.c demux_mpgaudio.c demux_nsf.c \ + demux_cdda.c demux_mpgaudio.c \ demux_realaudio.c demux_snd.c demux_voc.c \ demux_vox.c demux_wav.c demux_ac3.c id3.c \ demux_aac.c demux_mod.c demux_flac.c \ diff --git a/src/demuxers/demux_nsf.c b/src/demuxers/demux_nsf.c deleted file mode 100644 index 7408274d5..000000000 --- a/src/demuxers/demux_nsf.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (C) 2000-2003 the xine project - * - * This file is part of xine, a free video player. - * - * xine 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. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - */ - -/* - * NSF File "Demuxer" by Mike Melanson (melanson@pcisys.net) - * This is really just a loader for NES Music File Format (extension NSF) - * which loads an entire NSF file and passes it over to the NSF audio - * decoder. - * - * After the file is sent over, the demuxer controls the playback by - * sending empty buffers with incrementing pts values. - * - * For more information regarding the NSF format, visit: - * http://www.tripoint.org/kevtris/nes/nsfspec.txt - * - * $Id: demux_nsf.c,v 1.24 2007/03/29 17:03:06 dgp85 Exp $ - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include - -/********** logging **********/ -#define LOG_MODULE "demux_nsf" -/* #define LOG_VERBOSE */ -/* #define LOG */ - -#include "xine_internal.h" -#include "xineutils.h" -#include "compat.h" -#include "demux.h" -#include "bswap.h" -#include "group_audio.h" - -#define NSF_HEADER_SIZE 0x80 -#define NSF_SAMPLERATE 44100 -#define NSF_BITS 8 -#define NSF_CHANNELS 1 -#define NSF_REFRESH_RATE 60 -#define NSF_PTS_INC (90000 / NSF_REFRESH_RATE) - -typedef struct { - demux_plugin_t demux_plugin; - - xine_stream_t *stream; - fifo_buffer_t *video_fifo; - fifo_buffer_t *audio_fifo; - input_plugin_t *input; - int status; - - int total_songs; - int current_song; - int new_song; /* indicates song change */ - - char *title; - char *artist; - char *copyright; - - off_t filesize; - - int64_t current_pts; - int file_sent; -} demux_nsf_t; - -typedef struct { - demux_class_t demux_class; -} demux_nsf_class_t; - -/* returns 1 if the NSF file was opened successfully, 0 otherwise */ -static int open_nsf_file(demux_nsf_t *this) { - unsigned char header[NSF_HEADER_SIZE]; - - this->input->seek(this->input, 0, SEEK_SET); - if (this->input->read(this->input, header, NSF_HEADER_SIZE) != - NSF_HEADER_SIZE) - return 0; - - /* check for the signature */ - if ((header[0] != 'N') || - (header[1] != 'E') || - (header[2] != 'S') || - (header[3] != 'M') || - (header[4] != 0x1A)) - return 0; - - this->total_songs = header[6]; - this->current_song = header[7]; - this->title = strdup(&header[0x0E]); - this->artist = strdup(&header[0x2E]); - this->copyright = strdup(&header[0x4E]); - - this->filesize = this->input->get_length(this->input); - - return 1; -} - -static int demux_nsf_send_chunk(demux_plugin_t *this_gen) { - demux_nsf_t *this = (demux_nsf_t *) this_gen; - buf_element_t *buf; - int bytes_read; - char title[100]; - - /* send chunks of the file to the decoder until file is completely - * loaded; then send control buffers */ - if (!this->file_sent) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->type = BUF_AUDIO_NSF; - bytes_read = this->input->read(this->input, buf->content, buf->max_size); - - if (bytes_read == 0) { - /* the file has been completely loaded, free the buffer and start - * sending control buffers */ - buf->free_buffer(buf); - this->file_sent = 1; - - } else { - - /* keep loading the file */ - if (bytes_read < buf->max_size) - buf->size = bytes_read; - else - buf->size = buf->max_size; - - buf->extra_info->input_normpos = 0; - buf->extra_info->input_time = 0; - buf->pts = 0; - - this->audio_fifo->put (this->audio_fifo, buf); - } - } - - /* this is not an 'else' because control might fall through from above */ - if (this->file_sent) { - /* send a control buffer */ - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - - if (this->new_song) { - - buf->decoder_info[1] = this->current_song; - this->new_song = 0; - sprintf(title, "%s, song %d/%d", - this->title, this->current_song, this->total_songs); - - _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, title); - - _x_demux_control_newpts(this->stream, this->current_pts, 0); - - } else - buf->decoder_info[1] = 0; - - buf->type = BUF_AUDIO_NSF; - if(this->total_songs) - buf->extra_info->input_normpos = (this->current_song - 1) * 65535 / this->total_songs; - buf->extra_info->input_time = this->current_pts / 90; - buf->pts = this->current_pts; - buf->size = 0; - this->audio_fifo->put (this->audio_fifo, buf); - - this->current_pts += NSF_PTS_INC; - } - - return this->status; -} - -static void demux_nsf_send_headers(demux_plugin_t *this_gen) { - demux_nsf_t *this = (demux_nsf_t *) this_gen; - buf_element_t *buf; - char copyright[100]; - - this->video_fifo = this->stream->video_fifo; - this->audio_fifo = this->stream->audio_fifo; - - this->status = DEMUX_OK; - - /* load stream information */ - _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 0); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_CHANNELS, - NSF_CHANNELS); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE, - NSF_SAMPLERATE); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITS, - NSF_BITS); - - _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, this->title); - _x_meta_info_set(this->stream, XINE_META_INFO_ARTIST, this->artist); - sprintf(copyright, "(C) %s", this->copyright); - _x_meta_info_set(this->stream, XINE_META_INFO_COMMENT, copyright); - - /* send start buffers */ - _x_demux_control_start(this->stream); - - /* send init info to the audio decoder */ - if (this->audio_fifo) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->type = BUF_AUDIO_NSF; - buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_FRAME_END; - buf->decoder_info[0] = 5; - buf->decoder_info[1] = NSF_SAMPLERATE; - buf->decoder_info[2] = NSF_BITS; - buf->decoder_info[3] = NSF_CHANNELS; - - /* send the NSF filesize in the body, big endian format */ - buf->content[0] = (this->filesize >> 24) & 0xFF; - buf->content[1] = (this->filesize >> 16) & 0xFF; - buf->content[2] = (this->filesize >> 8) & 0xFF; - buf->content[3] = (this->filesize >> 0) & 0xFF; - /* send the requested song */ - buf->content[4] = this->current_song + 5; - - this->audio_fifo->put (this->audio_fifo, buf); - } -} - -static int demux_nsf_seek (demux_plugin_t *this_gen, - off_t start_pos, int start_time, int playing) { - - demux_nsf_t *this = (demux_nsf_t *) this_gen; - start_pos = (off_t) ( (double) start_pos / 65535 * - this->total_songs ); - - /* if thread is not running, initialize demuxer */ - if( !playing ) { - - /* send new pts */ - _x_demux_control_newpts(this->stream, 0, 0); - - this->status = DEMUX_OK; - - /* reposition stream at the start for loading */ - this->input->seek(this->input, 0, SEEK_SET); - - this->file_sent = 0; - this->current_pts = 0; - this->new_song = 1; - } else { - this->current_song = start_pos + 1; - this->new_song = 1; - this->current_pts = 0; - _x_demux_flush_engine(this->stream); - } - - return this->status; -} - -static void demux_nsf_dispose (demux_plugin_t *this_gen) { - demux_nsf_t *this = (demux_nsf_t *) this_gen; - - free(this->title); - free(this->artist); - free(this->copyright); - free(this); -} - -static int demux_nsf_get_status (demux_plugin_t *this_gen) { - demux_nsf_t *this = (demux_nsf_t *) this_gen; - - return this->status; -} - -/* return the approximate length in miliseconds */ -static int demux_nsf_get_stream_length (demux_plugin_t *this_gen) { - return 0; -} - -static uint32_t demux_nsf_get_capabilities(demux_plugin_t *this_gen) { - return DEMUX_CAP_NOCAP; -} - -static int demux_nsf_get_optional_data(demux_plugin_t *this_gen, - void *data, int data_type) { - return DEMUX_OPTIONAL_UNSUPPORTED; -} - -static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, - input_plugin_t *input) { - - demux_nsf_t *this; - - if (!INPUT_IS_SEEKABLE(input)) { - xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "input not seekable, can not handle!\n"); - return NULL; - } - - this = xine_xmalloc (sizeof (demux_nsf_t)); - this->stream = stream; - this->input = input; - - this->demux_plugin.send_headers = demux_nsf_send_headers; - this->demux_plugin.send_chunk = demux_nsf_send_chunk; - this->demux_plugin.seek = demux_nsf_seek; - this->demux_plugin.dispose = demux_nsf_dispose; - this->demux_plugin.get_status = demux_nsf_get_status; - this->demux_plugin.get_stream_length = demux_nsf_get_stream_length; - this->demux_plugin.get_capabilities = demux_nsf_get_capabilities; - this->demux_plugin.get_optional_data = demux_nsf_get_optional_data; - this->demux_plugin.demux_class = class_gen; - - this->status = DEMUX_FINISHED; - - switch (stream->content_detection_method) { - - case METHOD_BY_EXTENSION: { - const char *extensions, *mrl; - - mrl = input->get_mrl (input); - extensions = class_gen->get_extensions (class_gen); - - if (!_x_demux_check_extension (mrl, extensions)) { - free (this); - return NULL; - } - } - /* falling through is intended */ - - case METHOD_BY_CONTENT: - case METHOD_EXPLICIT: - - if (!open_nsf_file(this)) { - free (this); - return NULL; - } - - break; - - default: - free (this); - return NULL; - } - - return &this->demux_plugin; -} - -static const char *get_description (demux_class_t *this_gen) { - return "NES Music file demux plugin"; -} - -static const char *get_identifier (demux_class_t *this_gen) { - return "NSF"; -} - -static const char *get_extensions (demux_class_t *this_gen) { - return "nsf"; -} - -static const char *get_mimetypes (demux_class_t *this_gen) { - return NULL; -} - -static void class_dispose (demux_class_t *this_gen) { - demux_nsf_class_t *this = (demux_nsf_class_t *) this_gen; - - free (this); -} - -void *demux_nsf_init_plugin (xine_t *xine, void *data) { - demux_nsf_class_t *this; - - this = xine_xmalloc (sizeof (demux_nsf_class_t)); - - this->demux_class.open_plugin = open_plugin; - this->demux_class.get_description = get_description; - this->demux_class.get_identifier = get_identifier; - this->demux_class.get_mimetypes = get_mimetypes; - this->demux_class.get_extensions = get_extensions; - this->demux_class.dispose = class_dispose; - - return this; -} diff --git a/src/demuxers/group_audio.c b/src/demuxers/group_audio.c index b8f0e1ed4..4635ec4a6 100644 --- a/src/demuxers/group_audio.c +++ b/src/demuxers/group_audio.c @@ -71,10 +71,6 @@ static const demuxer_info_t demux_info_mpc = { 0 /* priority */ }; -static const demuxer_info_t demux_info_nsf = { - 10 /* priority */ -}; - static const demuxer_info_t demux_info_realaudio = { 10 /* priority */ }; @@ -120,7 +116,6 @@ const plugin_info_t xine_plugin_info[] EXPORTED = { { PLUGIN_DEMUX, 26, "flac", XINE_VERSION_CODE, &demux_info_flac, demux_flac_init_plugin }, { PLUGIN_DEMUX, 26, "mp3", XINE_VERSION_CODE, &demux_info_mpgaudio, demux_mpgaudio_init_class }, { PLUGIN_DEMUX, 26, "mpc", XINE_VERSION_CODE, &demux_info_mpc, demux_mpc_init_plugin }, - { PLUGIN_DEMUX, 26, "nsf", XINE_VERSION_CODE, &demux_info_nsf, demux_nsf_init_plugin }, { PLUGIN_DEMUX, 26, "realaudio", XINE_VERSION_CODE, &demux_info_realaudio, demux_realaudio_init_plugin }, { PLUGIN_DEMUX, 26, "shn", XINE_VERSION_CODE, &demux_info_shn, demux_shn_init_plugin }, { PLUGIN_DEMUX, 26, "snd", XINE_VERSION_CODE, &demux_info_snd, demux_snd_init_plugin }, diff --git a/src/demuxers/group_audio.h b/src/demuxers/group_audio.h index 7f1fccc5e..e5456aab6 100644 --- a/src/demuxers/group_audio.h +++ b/src/demuxers/group_audio.h @@ -34,7 +34,6 @@ void *demux_dts_init_plugin (xine_t *xine, void *data); void *demux_flac_init_plugin (xine_t *xine, void *data); void *demux_mpgaudio_init_class (xine_t *xine, void *data); void *demux_mpc_init_plugin (xine_t *xine, void *data); -void *demux_nsf_init_plugin (xine_t *xine, void *data); void *demux_realaudio_init_plugin (xine_t *xine, void *data); void *demux_shn_init_plugin (xine_t *xine, void *data); void *demux_snd_init_plugin (xine_t *xine, void *data); diff --git a/src/libxineadec/Makefile.am b/src/libxineadec/Makefile.am index 6ea2171ee..3bc08f320 100644 --- a/src/libxineadec/Makefile.am +++ b/src/libxineadec/Makefile.am @@ -29,12 +29,8 @@ $(top_builddir)/contrib/libmpcdec/libmpcdec.la: $(top_builddir)/contrib/libdca/libdca.la: $(MAKE) -C $(top_builddir)/contrib/libdca -$(top_builddir)/contrib/nosefart/libnosefart.la: - $(MAKE) -C $(top_builddir)/contrib/nosefart - xineplug_LTLIBRARIES = \ xineplug_decode_gsm610.la \ - xineplug_decode_nsf.la \ xineplug_decode_lpcm.la \ $(vorbis_module) \ $(speex_module) \ @@ -44,11 +40,6 @@ xineplug_LTLIBRARIES = \ xineplug_decode_gsm610_la_SOURCES = gsm610.c xineplug_decode_gsm610_la_LIBADD = $(XINE_LIB) gsm610/libgsm610.la -xineplug_decode_nsf_la_SOURCES = nsf.c -xineplug_decode_nsf_la_LIBADD = $(XINE_LIB) $(top_builddir)/contrib/nosefart/libnosefart.la -lm -xineplug_decode_nsf_la_CFLAGS = $(AM_CFLAGS) -fno-strict-aliasing -xineplug_decode_nsf_la_CPPFLAGS = $(AM_CPPFLAGS) -DNSF_PLAYER -I$(top_srcdir)/contrib/nosefart - xineplug_decode_lpcm_la_SOURCES = xine_lpcm_decoder.c xineplug_decode_lpcm_la_LIBADD = $(XINE_LIB) diff --git a/src/libxineadec/nsf.c b/src/libxineadec/nsf.c deleted file mode 100644 index 4af6fe878..000000000 --- a/src/libxineadec/nsf.c +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2000-2001 the xine project - * - * This file is part of xine, a free video player. - * - * xine 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. - * - * xine is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA - * - * NSF Audio "Decoder" using the Nosefart NSF engine by Matt Conte - * http://www.baisoku.org/ - * - * $Id: nsf.c,v 1.13 2006/09/25 23:56:31 dgp85 Exp $ - */ - -#include -#include -#include -#include -#include - -#include "xine_internal.h" -#include "audio_out.h" -#include "buffer.h" -#include "xineutils.h" -#include "bswap.h" - -/* Nosefart includes */ -#include "types.h" -#include "nsf.h" - -typedef struct { - audio_decoder_class_t decoder_class; -} nsf_class_t; - -typedef struct nsf_decoder_s { - audio_decoder_t audio_decoder; - - xine_stream_t *stream; - - int sample_rate; /* audio sample rate */ - int bits_per_sample; /* bits/sample, usually 8 or 16 */ - int channels; /* 1 or 2, usually */ - - int output_open; /* flag to indicate audio is ready */ - - int nsf_size; - unsigned char *nsf_file; - int nsf_index; - int song_number; - - /* nsf-specific variables */ - int64_t last_pts; - unsigned int iteration; - - nsf_t *nsf; -} nsf_decoder_t; - -/************************************************************************** - * xine audio plugin functions - *************************************************************************/ - -static void nsf_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { - - nsf_decoder_t *this = (nsf_decoder_t *) this_gen; - audio_buffer_t *audio_buffer; - - if (buf->decoder_flags & BUF_FLAG_HEADER) { - - /* When the engine sends a BUF_FLAG_HEADER flag, it is time to initialize - * the decoder. The buffer element type has 4 decoder_info fields, - * 0..3. Field 1 is the sample rate. Field 2 is the bits/sample. Field - * 3 is the number of channels. */ - this->sample_rate = buf->decoder_info[1]; - this->bits_per_sample = buf->decoder_info[2]; - this->channels = buf->decoder_info[3]; - - /* take this opportunity to initialize stream/meta information */ - _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, - "NES Music (Nosefart)"); - - this->song_number = buf->content[4]; - /* allocate a buffer for the file */ - this->nsf_size = BE_32(&buf->content[0]); - this->nsf_file = xine_xmalloc(this->nsf_size); - this->nsf_index = 0; - - /* peform any other required initialization */ - this->last_pts = -1; - this->iteration = 0; - - return; - } - - /* accumulate chunks from the NSF file until whole file is received */ - if (this->nsf_index < this->nsf_size) { - xine_fast_memcpy(&this->nsf_file[this->nsf_index], buf->content, - buf->size); - this->nsf_index += buf->size; - - if (this->nsf_index == this->nsf_size) { - /* file has been received, proceed to initialize engine */ - nsf_init(); - this->nsf = nsf_load(NULL, this->nsf_file, this->nsf_size); - if (!this->nsf) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "nsf: could not initialize NSF\n"); - /* make the decoder return on every subsequent buffer */ - this->nsf_index = 0; - return; - } - this->nsf->current_song = this->song_number; - nsf_playtrack(this->nsf, this->nsf->current_song, this->sample_rate, - this->bits_per_sample, this->channels); - } - return; - } - - /* if the audio output is not open yet, open the audio output */ - if (!this->output_open) { - this->output_open = this->stream->audio_out->open( - this->stream->audio_out, - this->stream, - this->bits_per_sample, - this->sample_rate, - _x_ao_channels2mode(this->channels)); - } - - /* if the audio still isn't open, do not go any further with the decode */ - if (!this->output_open) - return; - - /* check if a song change was requested */ - if (buf->decoder_info[1]) { - this->nsf->current_song = buf->decoder_info[1]; - nsf_playtrack(this->nsf, this->nsf->current_song, this->sample_rate, - this->bits_per_sample, this->channels); - } - - /* time to decode a frame */ - if (this->last_pts != -1) { - - /* process a frame */ - nsf_frame(this->nsf); - - /* get an audio buffer */ - audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); - if (audio_buffer->mem_size == 0) { - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "nsf: Help! Allocated audio buffer with nothing in it!\n"); - return; - } - - apu_process(audio_buffer->mem, this->sample_rate / this->nsf->playback_rate); - audio_buffer->vpts = buf->pts; - audio_buffer->num_frames = this->sample_rate / this->nsf->playback_rate; - this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); - } - this->last_pts = buf->pts; -} - -/* This function resets the state of the audio decoder. This usually - * entails resetting the data accumulation buffer. */ -static void nsf_reset (audio_decoder_t *this_gen) { - - nsf_decoder_t *this = (nsf_decoder_t *) this_gen; - - this->last_pts = -1; -} - -/* This function resets the last pts value of the audio decoder. */ -static void nsf_discontinuity (audio_decoder_t *this_gen) { - - nsf_decoder_t *this = (nsf_decoder_t *) this_gen; - - this->last_pts = -1; -} - -/* This function closes the audio output and frees the private audio decoder - * structure. */ -static void nsf_dispose (audio_decoder_t *this_gen) { - - nsf_decoder_t *this = (nsf_decoder_t *) this_gen; - - /* close the audio output */ - if (this->output_open) - this->stream->audio_out->close (this->stream->audio_out, this->stream); - this->output_open = 0; - - /* free anything that was allocated during operation */ - nsf_free(&this->nsf); - free(this->nsf_file); - free(this); -} - -/* This function allocates, initializes, and returns a private audio - * decoder structure. */ -static audio_decoder_t *open_plugin (audio_decoder_class_t *class_gen, xine_stream_t *stream) { - - nsf_decoder_t *this ; - - this = (nsf_decoder_t *) xine_xmalloc (sizeof (nsf_decoder_t)); - - /* connect the member functions */ - this->audio_decoder.decode_data = nsf_decode_data; - this->audio_decoder.reset = nsf_reset; - this->audio_decoder.discontinuity = nsf_discontinuity; - this->audio_decoder.dispose = nsf_dispose; - - /* connect the stream */ - this->stream = stream; - - /* audio output is not open at the start */ - this->output_open = 0; - - /* initialize the basic audio parameters */ - this->channels = 0; - this->sample_rate = 0; - this->bits_per_sample = 0; - - /* return the newly-initialized audio decoder */ - return &this->audio_decoder; -} - -/* This function returns a brief string that describes (usually with the - * decoder's most basic name) the audio decoder plugin. */ -static char *get_identifier (audio_decoder_class_t *this) { - return "NSF"; -} - -/* This function returns a slightly longer string describing the audio - * decoder plugin. */ -static char *get_description (audio_decoder_class_t *this) { - return "NES Music audio decoder plugin"; -} - -/* This function frees the audio decoder class and any other memory that was - * allocated. */ -static void dispose_class (audio_decoder_class_t *this_gen) { - - nsf_class_t *this = (nsf_class_t *)this_gen; - - free (this); -} - -/* This function allocates a private audio decoder class and initializes - * the class's member functions. */ -static void *init_plugin (xine_t *xine, void *data) { - - nsf_class_t *this ; - - this = (nsf_class_t *) xine_xmalloc (sizeof (nsf_class_t)); - - this->decoder_class.open_plugin = open_plugin; - this->decoder_class.get_identifier = get_identifier; - this->decoder_class.get_description = get_description; - this->decoder_class.dispose = dispose_class; - - return this; -} - -/* This is a list of all of the internal xine audio buffer types that - * this decoder is able to handle. Check src/xine-engine/buffer.h for a - * list of valid buffer types (and add a new one if the one you need does - * not exist). Terminate the list with a 0. */ -static uint32_t audio_types[] = { - BUF_AUDIO_NSF, - 0 -}; - -/* This data structure combines the list of supported xine buffer types and - * the priority that the plugin should be given with respect to other - * plugins that handle the same buffer type. A plugin with priority (n+1) - * will be used instead of a plugin with priority (n). */ -static const decoder_info_t dec_info_audio = { - audio_types, /* supported types */ - 5 /* priority */ -}; - -/* The plugin catalog entry. This is the only information that this plugin - * will export to the public. */ -const plugin_info_t xine_plugin_info[] EXPORTED = { - /* { type, API version, "name", version, special_info, init_function }, */ - { PLUGIN_AUDIO_DECODER, 15, "nsf", XINE_VERSION_CODE, &dec_info_audio, &init_plugin }, - { PLUGIN_NONE, 0, "", 0, NULL, NULL } -}; - -- cgit v1.2.3