Merge lp:~mgiuca/dosbox/fluidsynth into lp:~mgiuca/dosbox/trunk

Proposed by Matt Giuca on 2012-03-07
Status: Needs review
Proposed branch: lp:~mgiuca/dosbox/fluidsynth
Merge into: lp:~mgiuca/dosbox/trunk
Diff against target: 335 lines (+278/-2)
5 files modified
acinclude.m4 (+120/-0)
configure.in (+13/-0)
src/dosbox.cpp (+2/-2)
src/gui/midi.cpp (+6/-0)
src/gui/midi_fluidsynth.h (+137/-0)
To merge this branch: bzr merge lp:~mgiuca/dosbox/fluidsynth
Reviewer Review Type Date Requested Status
Matt Giuca Pending
Review via email: mp+96296@code.launchpad.net

Commit message

Added a new MIDI driver 'fluidsynth', for DOSBox to send MIDI commands directly to the FluidSynth API.

Description of the change

Added a new MIDI driver 'fluidsynth', which allows DOSBox's MPU-401 MIDI system to talk directly to the FluidSynth software synthesiser API, rather than sending MIDI commands to the system.

This provides a reliable software synthesiser back-end for DOSBox without having to manually set up a FluidSynth server and work out the correct ALSA port.

To post a comment you must log in.

Unmerged revisions

3696. By Matt Giuca on 2012-03-07

midi: Move FluidSynth to the top, so it is searched last when searching for the default driver.

3695. By Matt Giuca on 2012-03-07

midi_fluidsynth: Formatting to conform to DOSBox coding style.

3694. By Matt Giuca on 2012-03-07

midi_fluidsynth: The 'midiconfig' for this driver now contains the driver:soundfont pair separated by a colon.
This allows the user to specify the FluidSynth audio driver; it is no longer hard-coded to alsa.

3693. By Matt Giuca on 2012-03-06

midi_fluidsynth: Implemented PlaySysex and PlayMsg.
MIDI messages are now routed through to the FluidSynth API, so it all works.

3692. By Matt Giuca on 2012-03-06

midi_fluidsynth: Implemented Open and Close.
Now creates and destroys the FluidSynth driver, loading the soundfont from midiconfig.

3691. By Matt Giuca on 2012-03-06

gui/midi: Only include fluidsynth driver if HAVE_FLUID is defined.

3690. By Matt Giuca on 2012-03-06

Added FluidSynth to build scripts.

3689. By Matt Giuca on 2012-03-06

Added fluidsynth as a type of mididevice.
Currently just stubs (logs all method calls).

3688. By qbix79 on 2012-01-27

Add patch 3461824: Readme fixes by clem

3687. By qbix79 on 2012-01-27

Add cmd-q => exit for Mac OS X

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'acinclude.m4'
2--- acinclude.m4 2011-04-26 09:34:55 +0000
3+++ acinclude.m4 2012-03-07 05:50:24 +0000
4@@ -303,6 +303,126 @@
5 AC_SUBST(ALSA_LIBS)
6 ])
7
8+dnl Configure Paths for FluidSynth
9+dnl Modified from the ALSA code above by Matt Giuca <matt.giuca@gmail.com>
10+dnl Test for libfluidsynth, and define FLUID_CFLAGS and FLUID_LIBS as
11+dnl appropriate.
12+dnl AM_PATH_FLUID([MINIMUM-VERSION [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
13+dnl enables arguments --with-fluid-prefix=
14+dnl --with-fluid-inc-prefix=
15+dnl
16+dnl For backwards compatibility, if ACTION_IF_NOT_FOUND is not specified,
17+dnl and the FluidSynth libraries are not found, a fatal AC_MSG_ERROR() will
18+dnl result.
19+dnl
20+AC_DEFUN([AM_PATH_FLUID],
21+[dnl Save the original CFLAGS, LDFLAGS, and LIBS
22+fluid_save_CFLAGS="$CFLAGS"
23+fluid_save_LDFLAGS="$LDFLAGS"
24+fluid_save_LIBS="$LIBS"
25+fluid_found=yes
26+
27+dnl
28+dnl Get the cflags and libraries for fluidsynth
29+dnl
30+AC_ARG_WITH(fluid-prefix,
31+[ --with-fluid-prefix=PFX Prefix where FluidSynth library is installed (optional)],
32+[fluid_prefix="$withval"], [fluid_prefix=""])
33+
34+AC_ARG_WITH(fluid-inc-prefix,
35+[ --with-fluid-inc-prefix=PFX Prefix where include libraries are (optional)],
36+[fluid_inc_prefix="$withval"], [fluid_inc_prefix=""])
37+
38+dnl Add any special include directories
39+AC_MSG_CHECKING(for FluidSynth CFLAGS)
40+if test "$fluid_inc_prefix" != "" ; then
41+ FLUID_CFLAGS="$FLUID_CFLAGS -I$fluid_inc_prefix"
42+ CFLAGS="$CFLAGS -I$fluid_inc_prefix"
43+fi
44+AC_MSG_RESULT($FLUID_CFLAGS)
45+
46+dnl add any special lib dirs
47+AC_MSG_CHECKING(for FluidSynth LDFLAGS)
48+if test "$fluid_prefix" != "" ; then
49+ FLUID_LIBS="$FLUID_LIBS -L$fluid_prefix"
50+ LDFLAGS="$LDFLAGS $FLUID_LIBS"
51+fi
52+
53+dnl add the fluidsynth library
54+FLUID_LIBS="$FLUID_LIBS -lfluidsynth"
55+LIBS="$FLUID_LIBS $LIBS"
56+AC_MSG_RESULT($FLUID_LIBS)
57+
58+dnl Check for a working version of libfluidsynth that is of the right version.
59+min_fluid_version=ifelse([$1], ,1.1.2,$1)
60+AC_MSG_CHECKING(for libfluidsynth headers version >= $min_fluid_version)
61+no_fluid=""
62+ fluid_min_major_version=`echo $min_fluid_version | \
63+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
64+ fluid_min_minor_version=`echo $min_fluid_version | \
65+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
66+ fluid_min_micro_version=`echo $min_fluid_version | \
67+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
68+
69+AC_LANG_SAVE
70+AC_LANG_C
71+AC_TRY_COMPILE([
72+#include <fluidsynth.h>
73+], [
74+# if(FLUIDSYNTH_VERSION_MAJOR > $fluid_min_major_version)
75+ exit(0);
76+# else
77+# if(FLUIDSYNTH_VERSION_MAJOR < $fluid_min_major_version)
78+# error not present
79+# endif
80+
81+# if(FLUIDSYNTH_VERSION_MINOR > $fluid_min_minor_version)
82+ exit(0);
83+# else
84+# if(FLUIDSYNTH_VERSION_MINOR < $fluid_min_minor_version)
85+# error not present
86+# endif
87+
88+# if(FLUIDSYNTH_VERSION_MICRO < $fluid_min_micro_version)
89+# error not present
90+# endif
91+# endif
92+# endif
93+exit(0);
94+],
95+ [AC_MSG_RESULT(found.)],
96+ [AC_MSG_RESULT(not present.)
97+ ifelse([$3], , [AC_MSG_ERROR(Sufficiently new version of libfluidsynth not found.)])
98+ fluid_found=no]
99+)
100+AC_LANG_RESTORE
101+
102+dnl Now that we know that we have the right version, let's see if we have the library and not just the headers.
103+AC_CHECK_LIB([fluidsynth], [new_fluid_synth],,
104+ [ifelse([$3], , [AC_MSG_ERROR(No linkable libfluidsynth was found.)])
105+ fluid_found=no]
106+)
107+
108+if test "x$fluid_found" = "xyes" ; then
109+ ifelse([$2], , :, [$2])
110+ LIBS=`echo $LIBS | sed 's/-lfluidsynth//g'`
111+ LIBS=`echo $LIBS | sed 's/ //'`
112+ LIBS="-lfluidsynth $LIBS"
113+fi
114+if test "x$fluid_found" = "xno" ; then
115+ ifelse([$3], , :, [$3])
116+ CFLAGS="$fluid_save_CFLAGS"
117+ LDFLAGS="$fluid_save_LDFLAGS"
118+ LIBS="$fluid_save_LIBS"
119+ FLUID_CFLAGS=""
120+ FLUID_LIBS=""
121+fi
122+
123+dnl That should be it. Now just export out symbols:
124+AC_SUBST(FLUID_CFLAGS)
125+AC_SUBST(FLUID_LIBS)
126+])
127+
128 AH_TOP([
129 /*
130 * Copyright (C) 2002-2011 The DOSBox Team
131
132=== modified file 'configure.in'
133--- configure.in 2011-06-12 13:58:27 +0000
134+++ configure.in 2012-03-07 05:50:24 +0000
135@@ -182,6 +182,19 @@
136 CXXFLAGS="$CXXFLAGS $ALSA_CFLAGS"
137 fi
138
139+dnl enable disable fluidsynth and pass it's cflags to CXXFLAGS
140+AC_ARG_ENABLE(fluidsynth-midi,
141+AC_HELP_STRING([--enable-fluidsynth-midi],[compile with fluidsynth midi support (default yes)]),
142+[ case "${enableval}" in
143+ yes) fluid_midi=true;;
144+ no) fluid_midi=false;;
145+esac],
146+[fluid_midi=true])
147+if test x$fluid_midi = xtrue ; then
148+ AM_PATH_FLUID(1.1.2, AC_DEFINE(HAVE_FLUID,1,[Define to 1 to use FluidSynth for MIDI]) , : )
149+ CXXFLAGS="$CXXFLAGS $FLUID_CFLAGS"
150+fi
151+
152 #Check for big endian machine, should #define WORDS_BIGENDIAN if so
153 AC_C_BIGENDIAN
154
155
156=== modified file 'src/dosbox.cpp'
157--- src/dosbox.cpp 2011-11-01 17:00:19 +0000
158+++ src/dosbox.cpp 2012-03-07 05:50:24 +0000
159@@ -480,7 +480,7 @@
160
161 const char* mputypes[] = { "intelligent", "uart", "none",0};
162 // FIXME: add some way to offer the actually available choices.
163- const char *devices[] = { "default", "win32", "alsa", "oss", "coreaudio", "coremidi","none", 0};
164+ const char *devices[] = { "default", "win32", "alsa", "oss", "fluidsynth", "coreaudio", "coremidi","none", 0};
165 Pstring = secprop->Add_string("mpu401",Property::Changeable::WhenIdle,"intelligent");
166 Pstring->Set_values(mputypes);
167 Pstring->Set_help("Type of MPU-401 to emulate.");
168@@ -491,7 +491,7 @@
169
170 Pstring = secprop->Add_string("midiconfig",Property::Changeable::WhenIdle,"");
171 Pstring->Set_help("Special configuration options for the device driver. This is usually the id of the device you want to use.\n"
172- " or in the case of coreaudio, you can specify a soundfont here.\n"
173+ " or in the case of coreaudio or fluidsynth, you can specify a soundfont here.\n"
174 " When using a Roland MT-32 rev. 0 as midi output device, some games may require a delay in order to prevent 'buffer overflow' issues.\n"
175 " In that case, add 'delaysysex', for example: midiconfig=2 delaysysex\n"
176 " See the README/Manual for more details.");
177
178=== modified file 'src/gui/midi.cpp'
179--- src/gui/midi.cpp 2011-04-26 09:34:55 +0000
180+++ src/gui/midi.cpp 2012-03-07 05:50:24 +0000
181@@ -82,6 +82,12 @@
182
183 /* Include different midi drivers, lowest ones get checked first for default */
184
185+#if defined (HAVE_FLUID)
186+
187+#include "midi_fluidsynth.h"
188+
189+#endif
190+
191 #if defined(MACOSX)
192
193 #include "midi_coremidi.h"
194
195=== added file 'src/gui/midi_fluidsynth.h'
196--- src/gui/midi_fluidsynth.h 1970-01-01 00:00:00 +0000
197+++ src/gui/midi_fluidsynth.h 2012-03-07 05:50:24 +0000
198@@ -0,0 +1,137 @@
199+/*
200+ * Copyright (C) 2002-2011 The DOSBox Team
201+ *
202+ * This program is free software; you can redistribute it and/or modify
203+ * it under the terms of the GNU General Public License as published by
204+ * the Free Software Foundation; either version 2 of the License, or
205+ * (at your option) any later version.
206+ *
207+ * This program is distributed in the hope that it will be useful,
208+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
209+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
210+ * GNU General Public License for more details.
211+ *
212+ * You should have received a copy of the GNU General Public License
213+ * along with this program; if not, write to the Free Software
214+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
215+ */
216+
217+#include <fluidsynth.h>
218+#include <ctype.h>
219+#include <string>
220+#include <sstream>
221+
222+class MidiHandler_fluidsynth : public MidiHandler {
223+private:
224+ std::string audio_driver;
225+ std::string soundfont;
226+ int soundfont_id;
227+ fluid_settings_t *settings;
228+ fluid_synth_t *synth;
229+ fluid_audio_driver_t* adriver;
230+public:
231+ MidiHandler_fluidsynth() : MidiHandler() {};
232+ const char* GetName(void) { return "fluidsynth"; }
233+ void PlaySysex(Bit8u * sysex,Bitu len) {
234+ fluid_synth_sysex(synth, (char*) sysex, len, NULL, NULL, NULL, 0);
235+ }
236+
237+ void PlayMsg(Bit8u * msg) {
238+ unsigned char chanID = msg[0] & 0x0F;
239+ switch (msg[0] & 0xF0) {
240+ case 0x80:
241+ fluid_synth_noteoff(synth, chanID, msg[1]);
242+ break;
243+ case 0x90:
244+ fluid_synth_noteon(synth, chanID, msg[1], msg[2]);
245+ break;
246+ case 0xB0:
247+ fluid_synth_cc(synth, chanID, msg[1], msg[2]);
248+ break;
249+ case 0xC0:
250+ fluid_synth_program_change(synth, chanID, msg[1]);
251+ break;
252+ case 0xD0:
253+ fluid_synth_channel_pressure(synth, chanID, msg[1]);
254+ break;
255+ case 0xE0:{
256+ long theBend = ((long)msg[1] + (long)(msg[2] << 7));
257+ fluid_synth_pitch_bend(synth, chanID, theBend);
258+ }
259+ break;
260+ default:
261+ LOG(LOG_MISC,LOG_WARN)("MIDI:fluidsynth: Unknown Command: %08lx", (long)msg);
262+ break;
263+ }
264+ }
265+
266+ void Close(void) {
267+ if (soundfont_id >= 0) {
268+ fluid_synth_sfunload(synth, soundfont_id, 0);
269+ }
270+ delete_fluid_audio_driver(adriver);
271+ delete_fluid_synth(synth);
272+ delete_fluid_settings(settings);
273+ }
274+
275+ bool Open(const char * conf) {
276+ /* The 'midiconfig' for the fluidsynth driver is a string of the
277+ * following format:
278+ * audio_driver:soundfont
279+ * The audio_driver is the name of the FluidSynth audio driver (e.g.,
280+ * "jack" or "alsa"). The soundfont is the filename to the soundfont
281+ * to load.
282+ * If there is no colon, the whole string is the driver, and no
283+ * soundfont is loaded. If midiconfig is missing or empty, the driver
284+ * is the default.
285+ */
286+ if (conf && conf[0]) {
287+ std::string conf_str(conf);
288+ size_t delim_pos = conf_str.find(':');
289+ if (delim_pos == std::string::npos) {
290+ /* No colon; whole string is driver */
291+ audio_driver = conf_str;
292+ } else {
293+ /* Split string based on position of colon */
294+ audio_driver.assign(conf_str, 0, delim_pos);
295+ soundfont.assign(conf_str.c_str() + delim_pos + 1);
296+ }
297+ }
298+ settings = new_fluid_settings();
299+ if (!audio_driver.empty()) {
300+ fluid_settings_setstr(settings, "audio.driver", audio_driver.c_str());
301+ }
302+ synth = new_fluid_synth(settings);
303+ if (!synth) {
304+ LOG_MSG("MIDI:fluidsynth: Can't open synthesiser");
305+ delete_fluid_settings(settings);
306+ return false;
307+ }
308+ adriver = new_fluid_audio_driver(settings, synth);
309+ if (!adriver) {
310+ LOG_MSG("MIDI:fluidsynth: Can't create audio driver");
311+ delete_fluid_synth(synth);
312+ delete_fluid_settings(settings);
313+ return false;
314+ }
315+
316+ /* Optionally load a soundfont */
317+ if (!soundfont.empty()) {
318+ soundfont_id = fluid_synth_sfload(synth, soundfont.c_str(), 1);
319+ if (soundfont_id == FLUID_FAILED) {
320+ /* Just consider this a warning (fluidsynth already prints) */
321+ soundfont.clear();
322+ soundfont_id = -1;
323+ } else {
324+ LOG_MSG("MIDI:fluidsynth: loaded soundfont: %s",
325+ soundfont.c_str());
326+ }
327+ } else {
328+ soundfont_id = -1;
329+ LOG_MSG("MIDI:fluidsynth: no soundfont loaded");
330+ }
331+ return true;
332+ }
333+};
334+
335+MidiHandler_fluidsynth Midi_fluidsynth;

Subscribers

People subscribed via source and target branches

to all changes: