OpenTTD
libtimidity.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * 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/>.
8  */
9 
12 #include "../stdafx.h"
13 #include "../openttd.h"
14 #include "../sound_type.h"
15 #include "../debug.h"
16 #include "libtimidity.h"
17 #include "midifile.hpp"
18 #include "../base_media_base.h"
19 #include <fcntl.h>
20 #include <sys/types.h>
21 #include <sys/wait.h>
22 #include <unistd.h>
23 #include <signal.h>
24 #include <sys/stat.h>
25 #include <errno.h>
26 #include <timidity.h>
27 
28 #include "../safeguards.h"
29 
31 enum MidiState {
32  MIDI_STOPPED = 0,
33  MIDI_PLAYING = 1,
34 };
35 
36 static struct {
37  MidIStream *stream;
38  MidSongOptions options;
39  MidSong *song;
40 
41  MidiState status;
42  uint32 song_length;
43  uint32 song_position;
44 } _midi;
45 
48 
49 const char *MusicDriver_LibTimidity::Start(const char * const *param)
50 {
51  _midi.status = MIDI_STOPPED;
52  _midi.song = NULL;
53 
54  if (mid_init(param == NULL ? NULL : const_cast<char *>(param[0])) < 0) {
55  /* If init fails, it can be because no configuration was found.
56  * If it was not forced via param, try to load it without a
57  * configuration. Who knows that works. */
58  if (param != NULL || mid_init_no_config() < 0) {
59  return "error initializing timidity";
60  }
61  }
62  DEBUG(driver, 1, "successfully initialised timidity");
63 
64  _midi.options.rate = 44100;
65  _midi.options.format = MID_AUDIO_S16LSB;
66  _midi.options.channels = 2;
67  _midi.options.buffer_size = _midi.options.rate;
68 
69  return NULL;
70 }
71 
73 {
74  if (_midi.status == MIDI_PLAYING) this->StopSong();
75  mid_exit();
76 }
77 
79 {
80  std::string filename = MidiFile::GetSMFFile(song);
81 
82  this->StopSong();
83  if (filename.empty()) return;
84 
85  _midi.stream = mid_istream_open_file(filename.c_str());
86  if (_midi.stream == NULL) {
87  DEBUG(driver, 0, "Could not open music file");
88  return;
89  }
90 
91  _midi.song = mid_song_load(_midi.stream, &_midi.options);
92  mid_istream_close(_midi.stream);
93  _midi.song_length = mid_song_get_total_time(_midi.song);
94 
95  if (_midi.song == NULL) {
96  DEBUG(driver, 1, "Invalid MIDI file");
97  return;
98  }
99 
100  mid_song_start(_midi.song);
101  _midi.status = MIDI_PLAYING;
102 }
103 
105 {
106  _midi.status = MIDI_STOPPED;
107  /* mid_song_free cannot handle NULL! */
108  if (_midi.song != NULL) mid_song_free(_midi.song);
109  _midi.song = NULL;
110 }
111 
113 {
114  if (_midi.status == MIDI_PLAYING) {
115  _midi.song_position = mid_song_get_time(_midi.song);
116  if (_midi.song_position >= _midi.song_length) {
117  _midi.status = MIDI_STOPPED;
118  _midi.song_position = 0;
119  }
120  }
121 
122  return (_midi.status == MIDI_PLAYING);
123 }
124 
126 {
127  if (_midi.song != NULL) mid_song_set_volume(_midi.song, vol);
128 }
Metadata about a music track.
const char * Start(const char *const *param)
Start this driver.
Definition: libtimidity.cpp:49
bool IsSongPlaying()
Are we currently playing a song?
static FMusicDriver_LibTimidity iFMusicDriver_LibTimidity
Factory for the libtimidity driver.
Definition: libtimidity.cpp:47
MidiState
The state of playing.
Definition: libtimidity.cpp:31
static struct @25 _midi
Metadata about the midi we&#39;re playing.
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:36
void SetVolume(byte vol)
Set the volume, if possible.
static std::string GetSMFFile(const MusicSongInfo &song)
Get the name of a Standard MIDI File for a given song.
Definition: midifile.cpp:1041
Factory for the libtimidity driver.
Definition: libtimidity.h:35
void Stop()
Stop this driver.
Definition: libtimidity.cpp:72
void PlaySong(const MusicSongInfo &song)
Play a particular song.
Definition: libtimidity.cpp:78
Base for LibTimidity music playback.
void StopSong()
Stop playing the current song.