aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/sfx/player/polled.cpp
diff options
context:
space:
mode:
authorEugene Sandulenko2009-02-15 11:39:07 +0000
committerEugene Sandulenko2009-02-15 11:39:07 +0000
commite241843bec22600ab4ef98e7a085e82aac73fc93 (patch)
tree61a793884d3462e1feb80e80f202d8816d0c8ec4 /engines/sci/sfx/player/polled.cpp
parente9f742806362a84ffdb176a7414318dd2ab4df89 (diff)
downloadscummvm-rg350-e241843bec22600ab4ef98e7a085e82aac73fc93.tar.gz
scummvm-rg350-e241843bec22600ab4ef98e7a085e82aac73fc93.tar.bz2
scummvm-rg350-e241843bec22600ab4ef98e7a085e82aac73fc93.zip
- Remove some unneeded files
- Mass rename .c to .cpp svn-id: r38227
Diffstat (limited to 'engines/sci/sfx/player/polled.cpp')
-rw-r--r--engines/sci/sfx/player/polled.cpp335
1 files changed, 335 insertions, 0 deletions
diff --git a/engines/sci/sfx/player/polled.cpp b/engines/sci/sfx/player/polled.cpp
new file mode 100644
index 0000000000..2a4c23fa97
--- /dev/null
+++ b/engines/sci/sfx/player/polled.cpp
@@ -0,0 +1,335 @@
+/***************************************************************************
+ polled.c Copyright (C) 2004 Christoph Reichenbach
+
+
+ This program may be modified and copied freely according to the terms of
+ the GNU general public license (GPL), as long as the above copyright
+ notice and the licensing information contained herein are preserved.
+
+ Please refer to www.gnu.org for licensing details.
+
+ This work is provided AS IS, without warranty of any kind, expressed or
+ implied, including but not limited to the warranties of merchantibility,
+ noninfringement, and fitness for a specific purpose. The author will not
+ be held liable for any damage caused by this work or derivatives of it.
+
+ By using this source code, you agree to the licensing terms as stated
+ above.
+
+
+ Please contact the maintainer for bug reports or inquiries.
+
+ Current Maintainer:
+
+ Christoph Reichenbach (CR) <jameson@linuxgames.com>
+
+***************************************************************************/
+/* Polled player, mostly for PCM-based thingies (which _can_ poll, after all) */
+
+#include "sci/include/sfx_player.h"
+#include "sci/sfx/softseq.h"
+#include "sci/sfx/mixer.h"
+
+static song_iterator_t *play_it;
+static int play_paused = 0;
+static sfx_softseq_t *seq;
+static int volume = 100;
+static sfx_timestamp_t new_timestamp;
+static int new_song = 0;
+
+/* The time counter is used to determine how close to the end of a tick we are.
+** For each frame played, it is decreased by 60. */
+#define TIME_INC 60
+static int time_counter = 0;
+
+static void
+pp_tell_synth(int buf_nr, byte *buf)
+{
+ seq->handle_command(seq, buf[0], buf_nr-1, buf+1);
+}
+
+
+/*----------------------*/
+/* Mixer implementation */
+/*----------------------*/
+int
+ppf_poll(sfx_pcm_feed_t *self, byte *dest, int size)
+{
+ int written = 0;
+ byte buf[4];
+ int buf_nr;
+
+ if (!play_it)
+ return 0;
+
+ if (play_paused)
+ return 0;
+
+ while (written < size) {
+ int can_play;
+ int do_play;
+
+ while (time_counter <= TIME_INC) {
+ int next_stat = songit_next(&play_it,
+ &(buf[0]), &buf_nr,
+ IT_READER_MASK_ALL
+ | IT_READER_MAY_FREE
+ | IT_READER_MAY_CLEAN);
+
+ switch (next_stat) {
+ case SI_PCM:
+ sfx_play_iterator_pcm(play_it, 0);
+ break;
+
+ case SI_FINISHED:
+ songit_free(play_it);
+ play_it = NULL;
+ return written; /* We're done... */
+
+ case SI_IGNORE:
+ case SI_LOOP:
+ case SI_RELATIVE_CUE:
+ case SI_ABSOLUTE_CUE:
+ break; /* Boooring... .*/
+
+ case 0: /* MIDI command */
+
+ seq->handle_command(seq, buf[0], buf_nr - 1, buf+1);
+ break;
+
+ default:
+ time_counter += next_stat * seq->pcm_conf.rate;
+ }
+ }
+
+ can_play = time_counter / TIME_INC;
+ do_play = (can_play > (size - written))? (size - written) : can_play;
+
+ time_counter -= do_play * TIME_INC;
+
+ seq->poll(seq, dest + written * self->frame_size, do_play);
+ written += do_play;
+ }
+
+ return size; /* Apparently, we wrote all that was requested */
+}
+
+void
+ppf_destroy(sfx_pcm_feed_t *self)
+{
+ /* no-op */
+}
+
+int
+ppf_get_timestamp(sfx_pcm_feed_t *self, sfx_timestamp_t *timestamp)
+{
+ if (!new_song)
+ return PCM_FEED_IDLE;
+
+ /* Otherwise, we have a timestamp: */
+
+ *timestamp = new_timestamp;
+ new_song = 0;
+ return PCM_FEED_TIMESTAMP;
+}
+
+extern sfx_player_t sfx_player_polled;
+static
+sfx_pcm_feed_t pcmfeed = {
+ ppf_poll,
+ ppf_destroy,
+ ppf_get_timestamp,
+ NULL,
+ {0, 0, 0},
+ "polled-player-feed",
+ 0,
+ 0 /* filled in by the mixer */
+};
+
+/*=======================*/
+/* Player implementation */
+/*=======================*/
+
+
+/*--------------------*/
+/* API implementation */
+/*--------------------*/
+
+static void
+pp_timer_callback(void)
+{
+ /* Hey, we're polled anyway ;-) */
+}
+
+static int
+pp_set_option(char *name, char *value)
+{
+ return SFX_ERROR;
+}
+
+static int
+pp_init(resource_mgr_t *resmgr, int expected_latency)
+{
+ resource_t *res = NULL, *res2 = NULL;
+ int fd;
+
+ if (!mixer)
+ return SFX_ERROR;
+
+ /* FIXME Temporary hack to detect Amiga games. */
+ fd = sci_open("bank.001", O_RDONLY);
+
+ if (fd == SCI_INVALID_FD)
+ seq = sfx_find_softseq(NULL);
+ else {
+ close(fd);
+ seq = sfx_find_softseq("amiga");
+ }
+
+ if (!seq) {
+ sciprintf("[sfx:seq:polled] Initialisation failed: Could not find software sequencer\n");
+ return SFX_ERROR;
+ }
+
+ if (seq->patch_nr != SFX_SEQ_PATCHFILE_NONE) {
+ res = scir_find_resource(resmgr, sci_patch, seq->patch_nr, 0);
+ }
+
+ if (seq->patch2_nr != SFX_SEQ_PATCHFILE_NONE) {
+ res2 = scir_find_resource(resmgr, sci_patch, seq->patch2_nr, 0);
+ }
+
+ if (seq->init(seq,
+ (res)? res->data : NULL,
+ (res)? res->size : 0,
+ (res2)? res2->data : NULL,
+ (res2)? res2->size : 0)) {
+ sciprintf("[sfx:seq:polled] Initialisation failed: Sequencer '%s', v%s failed to initialise\n",
+ seq->name, seq->version);
+ return SFX_ERROR;
+ }
+
+ pcmfeed.conf = seq->pcm_conf;
+
+ seq->set_volume(seq, volume);
+ mixer->subscribe(mixer, &pcmfeed);
+
+ sfx_player_polled.polyphony = seq->polyphony;
+ return SFX_OK;
+}
+
+static int
+pp_add_iterator(song_iterator_t *it, GTimeVal start_time)
+{
+ song_iterator_t *old = play_it;
+
+ SIMSG_SEND(it, SIMSG_SET_PLAYMASK(seq->playmask));
+ SIMSG_SEND(it, SIMSG_SET_RHYTHM(seq->play_rhythm));
+
+ if (play_it == NULL)
+ seq->allstop(seq);
+
+ play_it = sfx_iterator_combine(play_it, it);
+
+ seq->set_volume(seq, volume);
+
+ /* The check must happen HERE, and not at the beginning of the
+ function, to avoid a race condition with the mixer. */
+ if (old == NULL) {
+ new_timestamp = sfx_new_timestamp(start_time.tv_sec,
+ start_time.tv_usec,
+ seq->pcm_conf.rate);
+ /* ASAP otherwise */
+ time_counter = 0;
+ new_song = 1;
+ }
+
+ return SFX_OK;
+}
+
+static int
+pp_fade_out(void)
+{
+ fprintf(stderr, __FILE__": Attempt to fade out- not implemented yet\n");
+ return SFX_ERROR;
+}
+
+static int
+pp_stop(void)
+{
+ song_iterator_t *it = play_it;
+
+ play_it = NULL;
+fprintf(stderr, "[play] Now stopping it %p\n", (void *)it);
+ if (it)
+ songit_free(it);
+
+ seq->allstop(seq);
+
+ return SFX_OK;
+}
+
+static int
+pp_send_iterator_message(song_iterator_message_t msg)
+{
+ if (!play_it)
+ return SFX_ERROR;
+
+ songit_handle_message(&play_it, msg);
+ return SFX_OK;
+}
+
+static int
+pp_pause(void)
+{
+ play_paused = 1;
+ seq->set_volume(seq, 0);
+
+ return SFX_OK;
+}
+
+static int
+pp_resume(void)
+{
+ if (!play_it)
+ {
+ play_paused = 0;
+ return SFX_OK; /* Nothing to resume */
+ }
+
+ if (play_paused)
+ new_song = 1; /* Fake starting a new song, re-using the old
+ ** time stamp (now long in the past) to indicate
+ ** resuming ASAP */
+
+ play_paused = 0;
+ seq->set_volume(seq, volume);
+ return SFX_OK;
+}
+
+static int
+pp_exit(void)
+{
+ seq->exit(seq);
+ songit_free(play_it);
+ play_it = NULL;
+
+ return SFX_OK;
+}
+
+sfx_player_t sfx_player_polled = {
+ "polled",
+ "0.1",
+ &pp_set_option,
+ &pp_init,
+ &pp_add_iterator,
+ &pp_fade_out,
+ &pp_stop,
+ &pp_send_iterator_message,
+ &pp_pause,
+ &pp_resume,
+ &pp_exit,
+ &pp_timer_callback,
+ &pp_tell_synth,
+ 0 /* polyphony */
+};