|
@@ -38,24 +38,26 @@
|
|
|
#undef OTTD_Random
|
|
|
#undef WindowClass
|
|
|
#undef SL_ERROR
|
|
|
#undef bool
|
|
|
|
|
|
#include <assert.h>
|
|
|
#include <unistd.h>
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
// we need to include debug.h after CoreServices because defining DEBUG will break CoreServices in OSX 10.2
|
|
|
#include "../debug.h"
|
|
|
|
|
|
static FMusicDriver_QtMidi iFMusicDriver_QtMidi;
|
|
|
|
|
|
|
|
|
enum {
|
|
|
midiType = 'Midi' /**< OSType code for MIDI songs. */
|
|
|
};
|
|
|
|
|
|
|
|
|
/**
|
|
|
* Converts a Unix-like pathname to a @c FSSpec structure which may be
|
|
|
* used with functions from several MacOS X frameworks (Carbon, QuickTime,
|
|
|
* etc). The pointed file or directory must exist.
|
|
|
*
|
|
|
* @param *path A string containing a Unix-like path.
|
|
@@ -198,48 +200,45 @@ enum {
|
|
|
|
|
|
static Movie _quicktime_movie; /**< Current QuickTime @c Movie. */
|
|
|
static byte _quicktime_volume = 127; /**< Current volume. */
|
|
|
static int _quicktime_state = QT_STATE_IDLE; /**< Current player state. */
|
|
|
|
|
|
|
|
|
/**
|
|
|
* Maps OpenTTD volume to QuickTime notion of volume.
|
|
|
*/
|
|
|
#define VOLUME ((short)((0x00FF & _quicktime_volume) << 1))
|
|
|
|
|
|
|
|
|
static void StopSong();
|
|
|
|
|
|
|
|
|
/**
|
|
|
* Initialized the MIDI player, including QuickTime initialization.
|
|
|
*
|
|
|
* @todo Give better error messages by inspecting error codes returned by
|
|
|
* @c Gestalt() and @c EnterMovies(). Needs changes in
|
|
|
* #InitQuickTimeIfNeeded.
|
|
|
*/
|
|
|
static const char* StartDriver(const char * const *parm)
|
|
|
const char *MusicDriver_QtMidi::Start(const char * const *parm)
|
|
|
{
|
|
|
InitQuickTimeIfNeeded();
|
|
|
return (_quicktime_started) ? NULL : "can't initialize QuickTime";
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
* Checks wether the player is active.
|
|
|
*
|
|
|
* This function is called at regular intervals from OpenTTD's main loop, so
|
|
|
* we call @c MoviesTask() from here to let QuickTime do its work.
|
|
|
*/
|
|
|
static bool SongIsPlaying()
|
|
|
bool MusicDriver_QtMidi::IsSongPlaying()
|
|
|
{
|
|
|
if (!_quicktime_started) return true;
|
|
|
|
|
|
switch (_quicktime_state) {
|
|
|
case QT_STATE_IDLE:
|
|
|
case QT_STATE_STOP:
|
|
|
/* Do nothing. */
|
|
|
break;
|
|
|
case QT_STATE_PLAY:
|
|
|
MoviesTask(_quicktime_movie, 0);
|
|
|
/* Check wether movie ended. */
|
|
|
if (IsMovieDone(_quicktime_movie) ||
|
|
@@ -249,25 +248,25 @@ static bool SongIsPlaying()
|
|
|
}
|
|
|
|
|
|
return _quicktime_state == QT_STATE_PLAY;
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
* Stops the MIDI player.
|
|
|
*
|
|
|
* Stops playing and frees any used resources before returning. As it
|
|
|
* deinitilizes QuickTime, the #_quicktime_started flag is set to @c false.
|
|
|
*/
|
|
|
static void StopDriver()
|
|
|
void MusicDriver_QtMidi::Stop()
|
|
|
{
|
|
|
if (!_quicktime_started) return;
|
|
|
|
|
|
DEBUG(driver, 2, "qtmidi: stopping driver...");
|
|
|
switch (_quicktime_state) {
|
|
|
case QT_STATE_IDLE:
|
|
|
DEBUG(driver, 3, "qtmidi: stopping not needed, already idle");
|
|
|
/* Do nothing. */
|
|
|
break;
|
|
|
case QT_STATE_PLAY:
|
|
|
StopSong();
|
|
|
case QT_STATE_STOP:
|
|
@@ -275,25 +274,25 @@ static void StopDriver()
|
|
|
}
|
|
|
|
|
|
ExitMovies();
|
|
|
_quicktime_started = false;
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
* Starts playing a new song.
|
|
|
*
|
|
|
* @param filename Path to a MIDI file.
|
|
|
*/
|
|
|
static void PlaySong(const char *filename)
|
|
|
void MusicDriver_QtMidi::PlaySong(const char *filename)
|
|
|
{
|
|
|
if (!_quicktime_started) return;
|
|
|
|
|
|
DEBUG(driver, 2, "qtmidi: trying to play '%s'", filename);
|
|
|
switch (_quicktime_state) {
|
|
|
case QT_STATE_PLAY:
|
|
|
StopSong();
|
|
|
DEBUG(driver, 3, "qtmidi: previous tune stopped");
|
|
|
/* XXX Fall-through -- no break needed. */
|
|
|
case QT_STATE_STOP:
|
|
|
DisposeMovie(_quicktime_movie);
|
|
|
DEBUG(driver, 3, "qtmidi: previous tune disposed");
|
|
@@ -303,25 +302,25 @@ static void PlaySong(const char *filenam
|
|
|
LoadMovieForMIDIFile(filename, &_quicktime_movie);
|
|
|
SetMovieVolume(_quicktime_movie, VOLUME);
|
|
|
StartMovie(_quicktime_movie);
|
|
|
_quicktime_state = QT_STATE_PLAY;
|
|
|
}
|
|
|
DEBUG(driver, 3, "qtmidi: playing '%s'", filename);
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
* Stops playing the current song, if the player is active.
|
|
|
*/
|
|
|
static void StopSong()
|
|
|
void MusicDriver_QtMidi::StopSong()
|
|
|
{
|
|
|
if (!_quicktime_started) return;
|
|
|
|
|
|
switch (_quicktime_state) {
|
|
|
case QT_STATE_IDLE:
|
|
|
/* XXX Fall-through -- no break needed. */
|
|
|
case QT_STATE_STOP:
|
|
|
DEBUG(driver, 3, "qtmidi: stop requested, but already idle");
|
|
|
/* Do nothing. */
|
|
|
break;
|
|
|
case QT_STATE_PLAY:
|
|
|
StopMovie(_quicktime_movie);
|
|
@@ -331,41 +330,29 @@ static void StopSong()
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
* Changes the playing volume of the MIDI player.
|
|
|
*
|
|
|
* As QuickTime controls volume in a per-movie basis, the desired volume is
|
|
|
* stored in #_quicktime_volume, and the volume is set here using the
|
|
|
* #VOLUME macro, @b and when loading new song in #PlaySong.
|
|
|
*
|
|
|
* @param vol The desired volume, range of the value is @c 0-127
|
|
|
*/
|
|
|
static void SetVolume(byte vol)
|
|
|
void MusicDriver_QtMidi::SetVolume(byte vol)
|
|
|
{
|
|
|
if (!_quicktime_started) return;
|
|
|
|
|
|
_quicktime_volume = vol;
|
|
|
|
|
|
DEBUG(driver, 2, "qtmidi: set volume to %u (%hi)", vol, VOLUME);
|
|
|
switch (_quicktime_state) {
|
|
|
case QT_STATE_IDLE:
|
|
|
/* Do nothing. */
|
|
|
break;
|
|
|
case QT_STATE_PLAY:
|
|
|
case QT_STATE_STOP:
|
|
|
SetMovieVolume(_quicktime_movie, VOLUME);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
* Table of callbacks that implement the QuickTime MIDI player.
|
|
|
*/
|
|
|
const HalMusicDriver _qtime_music_driver = {
|
|
|
StartDriver,
|
|
|
StopDriver,
|
|
|
PlaySong,
|
|
|
StopSong,
|
|
|
SongIsPlaying,
|
|
|
SetVolume,
|
|
|
};
|