libtimidity.cpp

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

Generated on Sun May 15 19:20:09 2011 for OpenTTD by  doxygen 1.6.1