Files @ r7377:722cd70012ed
Branch filter:

Location: cpp/openttd-patchpack/source/src/music/libtimidity.cpp

rubidium
(svn r10746) -Codechange: add a generic superclass for almost all pool items so we do not have to duplicate code for each of the pool item classes and use it for the station and roadstop classes.
/* $Id$ */

#include "../stdafx.h"
#include "../openttd.h"
#include "../sound.h"
#include "../string.h"
#include "../variables.h"
#include "../debug.h"
#include "libtimidity.h"
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <errno.h>
#include <timidity.h>
#if defined(PSP)
#include <pspaudiolib.h>
#endif /* PSP */

enum MidiState {
	MIDI_STOPPED = 0,
	MIDI_PLAYING = 1,
};

static struct {
	MidIStream *stream;
	MidSongOptions options;
	MidSong *song;

	MidiState status;
	uint32 song_length;
	uint32 song_position;
} _midi;

#if defined(PSP)
static void AudioOutCallback(void *buf, unsigned int _reqn, void *userdata)
{
	memset(buf, 0, _reqn * PSP_NUM_AUDIO_CHANNELS);
	if (_midi.status == MIDI_PLAYING) {
		mid_song_read_wave(_midi.song, buf, _reqn * PSP_NUM_AUDIO_CHANNELS);
	}
}
#endif /* PSP */

static FMusicDriver_LibTimidity iFMusicDriver_LibTimidity;

const char *MusicDriver_LibTimidity::Start(const char *const *param)
{
	_midi.status = MIDI_STOPPED;

	if (mid_init(param == NULL ? NULL : (char *)param[0]) < 0) {
		/* If init fails, it can be because no configuration was found.
		 *  If it was not forced via param, try to load it without a
		 *  configuration. Who knows that works. */
		if (param != NULL || mid_init_no_config() < 0) {
			return "error initializing timidity";
		}
	}
	DEBUG(driver, 1, "successfully initialised timidity");

	_midi.options.rate = 44100;
	_midi.options.format = MID_AUDIO_S16LSB;
	_midi.options.channels = 2;
#if defined(PSP)
	_midi.options.buffer_size = PSP_NUM_AUDIO_SAMPLES;
#else
	_midi.options.buffer_size = _midi.options.rate;
#endif

#if defined(PSP)
	pspAudioInit();
	pspAudioSetChannelCallback(_midi.options.channels, &AudioOutCallback, NULL);
	pspAudioSetVolume(_midi.options.channels, PSP_VOLUME_MAX, PSP_VOLUME_MAX);
#endif /* PSP */

	return NULL;
}

void MusicDriver_LibTimidity::Stop()
{
	if (_midi.status == MIDI_PLAYING) {
		_midi.status = MIDI_STOPPED;
		mid_song_free(_midi.song);
	}
	mid_exit();
}

void MusicDriver_LibTimidity::PlaySong(const char *filename)
{
	_midi.stream = mid_istream_open_file(filename);
	if (_midi.stream == NULL) {
		DEBUG(driver, 0, "Could not open music file");
		return;
	}

	_midi.song = mid_song_load(_midi.stream, &_midi.options);
	mid_istream_close(_midi.stream);
	_midi.song_length = mid_song_get_total_time(_midi.song);

	if (_midi.song == NULL) {
		DEBUG(driver, 1, "Invalid MIDI file");
		return;
	}

	mid_song_start(_midi.song);
	_midi.status = MIDI_PLAYING;
}

void MusicDriver_LibTimidity::StopSong()
{
	_midi.status = MIDI_STOPPED;
	mid_song_free(_midi.song);
}

bool MusicDriver_LibTimidity::IsSongPlaying()
{
	if (_midi.status == MIDI_PLAYING) {
		_midi.song_position = mid_song_get_time(_midi.song);
		if (_midi.song_position >= _midi.song_length) {
			_midi.status = MIDI_STOPPED;
			_midi.song_position = 0;
		}
	}

	return (_midi.status == MIDI_PLAYING);
}

void MusicDriver_LibTimidity::SetVolume(byte vol)
{
	if (_midi.song != NULL)
		mid_song_set_volume(_midi.song, vol);
}