OpenTTD: src/music/libtimidity.cpp Source File

OpenTTD

- Main Page
- Related Pages
- Modules
- Namespaces
- Data Structures
- Files

- File List
- Globals

libtimidity.cpp
Go to the documentation of this file.
1 /* $Id: libtimidity.cpp 26482 2014-04-23 20:13:33Z rubidium $ */
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 <fcntl.h>
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #include <unistd.h>
21 #include <signal.h>
22 #include <sys/stat.h>
23 #include <errno.h>
24 #include <timidity.h>
25 #if defined(PSP)
26 #include <pspaudiolib.h>
27 #endif /* PSP */
28
29 #include "../safeguards.h"
30
32 enum MidiState {
33 MIDI_STOPPED = 0,
34 MIDI_PLAYING = 1,
35 };
36
37 static struct {
38 MidIStream *stream;
39 MidSongOptions options;
40 MidSong *song;
41
42 MidiState status;
43 uint32 song_length;
44 uint32 song_position;
45 } _midi;
46
47 #if defined(PSP)
48 static void AudioOutCallback(void *buf, unsigned int _reqn, void *userdata)
49 {
50 memset(buf, 0, _reqn * PSP_NUM_AUDIO_CHANNELS);
51 if (_midi.status == MIDI_PLAYING) {
52 mid_song_read_wave(_midi.song, buf, _reqn * PSP_NUM_AUDIO_CHANNELS);
53 }
54 }
55 #endif /* PSP */
56
58 static FMusicDriver_LibTimidity iFMusicDriver_LibTimidity;
59
60 const char *MusicDriver_LibTimidity::Start(const char * const *param)
61 {
62 _midi.status = MIDI_STOPPED;
63 _midi.song = NULL;
64
65 if (mid_init(param == NULL ? NULL : const_cast<char *>(param[0])) < 0) {
66 /* If init fails, it can be because no configuration was found.
67 * If it was not forced via param, try to load it without a
68 * configuration. Who knows that works. */
69 if (param != NULL || mid_init_no_config() < 0) {
70 return "error initializing timidity";
71 }
72 }
73 DEBUG(driver, 1, "successfully initialised timidity");
74
75 _midi.options.rate = 44100;
76 _midi.options.format = MID_AUDIO_S16LSB;
77 _midi.options.channels = 2;
78 #if defined(PSP)
79 _midi.options.buffer_size = PSP_NUM_AUDIO_SAMPLES;
80 #else
81 _midi.options.buffer_size = _midi.options.rate;
82 #endif
83
84 #if defined(PSP)
85 pspAudioInit();
86 pspAudioSetChannelCallback(_midi.options.channels, &AudioOutCallback, NULL);
87 pspAudioSetVolume(_midi.options.channels, PSP_VOLUME_MAX, PSP_VOLUME_MAX);
88 #endif /* PSP */
89
90 return NULL;
91 }
92
93 void MusicDriver_LibTimidity::Stop()
94 {
95 if (_midi.status == MIDI_PLAYING) this->StopSong();
96 mid_exit();
97 }
98
99 void MusicDriver_LibTimidity::PlaySong(const char *filename)
100 {
101 this->StopSong();
102
103 _midi.stream = mid_istream_open_file(filename);
104 if (_midi.stream == NULL) {
105 DEBUG(driver, 0, "Could not open music file");
106 return;
107 }
108
109 _midi.song = mid_song_load(_midi.stream, &_midi.options);
110 mid_istream_close(_midi.stream);
111 _midi.song_length = mid_song_get_total_time(_midi.song);
112
113 if (_midi.song == NULL) {
114 DEBUG(driver, 1, "Invalid MIDI file");
115 return;
116 }
117
118 mid_song_start(_midi.song);
119 _midi.status = MIDI_PLAYING;
120 }
121
122 void MusicDriver_LibTimidity::StopSong()
123 {
124 _midi.status = MIDI_STOPPED;
125 /* mid_song_free cannot handle NULL! */
126 if (_midi.song != NULL) mid_song_free(_midi.song);
127 _midi.song = NULL;
128 }
129
130 bool MusicDriver_LibTimidity::IsSongPlaying()
131 {
132 if (_midi.status == MIDI_PLAYING) {
133 _midi.song_position = mid_song_get_time(_midi.song);
134 if (_midi.song_position >= _midi.song_length) {
135 _midi.status = MIDI_STOPPED;
136 _midi.song_position = 0;
137 }
138 }
139
140 return (_midi.status == MIDI_PLAYING);
141 }
142
143 void MusicDriver_LibTimidity::SetVolume(byte vol)
144 {
145 if (_midi.song != NULL) mid_song_set_volume(_midi.song, vol);
146 }