# libtimidity.cpp

Go to the documentation of this file.

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