# libtimidity.cpp

Go to the documentation of this file.

    00001 /* $Id: libtimidity.cpp 15903 2009-03-30 23:15:05Z rubidium $ */
    00002
    00005 #include "../stdafx.h"
    00006 #include "../openttd.h"
    00007 #include "../sound_type.h"
    00008 #include "../variables.h"
    00009 #include "../debug.h"
    00010 #include "libtimidity.h"
    00011 #include <fcntl.h>
    00012 #include <sys/types.h>
    00013 #include <sys/wait.h>
    00014 #include <unistd.h>
    00015 #include <signal.h>
    00016 #include <sys/stat.h>
    00017 #include <errno.h>
    00018 #include <timidity.h>
    00019 #if defined(PSP)
    00020 #include <pspaudiolib.h>
    00021 #endif /* PSP */
    00022
    00023 enum MidiState {
    00024   MIDI_STOPPED = 0,
    00025   MIDI_PLAYING = 1,
    00026 };
    00027
    00028 static struct {
    00029   MidIStream *stream;
    00030   MidSongOptions options;
    00031   MidSong *song;
    00032
    00033   MidiState status;
    00034   uint32 song_length;
    00035   uint32 song_position;
    00036 } _midi;
    00037
    00038 #if defined(PSP)
    00039 static void AudioOutCallback(void *buf, unsigned int _reqn, void *userdata)
    00040 {
    00041   memset(buf, 0, _reqn * PSP_NUM_AUDIO_CHANNELS);
    00042   if (_midi.status == MIDI_PLAYING) {
    00043     mid_song_read_wave(_midi.song, buf, _reqn * PSP_NUM_AUDIO_CHANNELS);
    00044   }
    00045 }
    00046 #endif /* PSP */
    00047
    00048 static FMusicDriver_LibTimidity iFMusicDriver_LibTimidity;
    00049
    00050 const char *MusicDriver_LibTimidity::Start(const char * const *param)
    00051 {
    00052   _midi.status = MIDI_STOPPED;
    00053   _midi.song = NULL;
    00054
    00055   if (mid_init(param == NULL ? NULL : (char *)param[0]) < 0) {
    00056     /* If init fails, it can be because no configuration was found.
    00057      *  If it was not forced via param, try to load it without a
    00058      *  configuration. Who knows that works. */
    00059     if (param != NULL || mid_init_no_config() < 0) {
    00060       return "error initializing timidity";
    00061     }
    00062   }
    00063   DEBUG(driver, 1, "successfully initialised timidity");
    00064
    00065   _midi.options.rate = 44100;
    00066   _midi.options.format = MID_AUDIO_S16LSB;
    00067   _midi.options.channels = 2;
    00068 #if defined(PSP)
    00069   _midi.options.buffer_size = PSP_NUM_AUDIO_SAMPLES;
    00070 #else
    00071   _midi.options.buffer_size = _midi.options.rate;
    00072 #endif
    00073
    00074 #if defined(PSP)
    00075   pspAudioInit();
    00076   pspAudioSetChannelCallback(_midi.options.channels, &AudioOutCallback, NULL);
    00077   pspAudioSetVolume(_midi.options.channels, PSP_VOLUME_MAX, PSP_VOLUME_MAX);
    00078 #endif /* PSP */
    00079
    00080   return NULL;
    00081 }
    00082
    00083 void MusicDriver_LibTimidity::Stop()
    00084 {
    00085   if (_midi.status == MIDI_PLAYING) this->StopSong();
    00086   mid_exit();
    00087 }
    00088
    00089 void MusicDriver_LibTimidity::PlaySong(const char *filename)
    00090 {
    00091   this->StopSong();
    00092
    00093   _midi.stream = mid_istream_open_file(filename);
    00094   if (_midi.stream == NULL) {
    00095     DEBUG(driver, 0, "Could not open music file");
    00096     return;
    00097   }
    00098
    00099   _midi.song = mid_song_load(_midi.stream, &_midi.options);
    00100   mid_istream_close(_midi.stream);
    00101   _midi.song_length = mid_song_get_total_time(_midi.song);
    00102
    00103   if (_midi.song == NULL) {
    00104     DEBUG(driver, 1, "Invalid MIDI file");
    00105     return;
    00106   }
    00107
    00108   mid_song_start(_midi.song);
    00109   _midi.status = MIDI_PLAYING;
    00110 }
    00111
    00112 void MusicDriver_LibTimidity::StopSong()
    00113 {
    00114   _midi.status = MIDI_STOPPED;
    00115   /* mid_song_free cannot handle NULL! */
    00116   if (_midi.song != NULL) mid_song_free(_midi.song);
    00117   _midi.song = NULL;
    00118 }
    00119
    00120 bool MusicDriver_LibTimidity::IsSongPlaying()
    00121 {
    00122   if (_midi.status == MIDI_PLAYING) {
    00123     _midi.song_position = mid_song_get_time(_midi.song);
    00124     if (_midi.song_position >= _midi.song_length) {
    00125       _midi.status = MIDI_STOPPED;
    00126       _midi.song_position = 0;
    00127     }
    00128   }
    00129
    00130   return (_midi.status == MIDI_PLAYING);
    00131 }
    00132
    00133 void MusicDriver_LibTimidity::SetVolume(byte vol)
    00134 {
    00135   if (_midi.song != NULL) mid_song_set_volume(_midi.song, vol);
    00136 }